17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <memdraw.h>
57dd7cddfSDavid du Colombier #include <pool.h>
67dd7cddfSDavid du Colombier
76a9fc400SDavid du Colombier extern Pool* imagmem;
859cc4ca5SDavid du Colombier int drawdebug;
96a9fc400SDavid du Colombier static int tablesbuilt;
1059cc4ca5SDavid du Colombier
117dd7cddfSDavid du Colombier /* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */
127dd7cddfSDavid du Colombier #define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19)
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier /*
157dd7cddfSDavid du Colombier * for 0 ≤ x ≤ 255*255, (x*0x0101+0x100)>>16 is a perfect approximation.
167dd7cddfSDavid du Colombier * for 0 ≤ x < (1<<16), x/255 = ((x+1)*0x0101)>>16 is a perfect approximation.
177dd7cddfSDavid du Colombier * the last one is perfect for all up to 1<<16, avoids a multiply, but requires a rathole.
187dd7cddfSDavid du Colombier */
197dd7cddfSDavid du Colombier /* #define DIV255(x) (((x)*257+256)>>16) */
207dd7cddfSDavid du Colombier #define DIV255(x) ((((x)+1)*257)>>16)
217dd7cddfSDavid du Colombier /* #define DIV255(x) (tmp=(x)+1, (tmp+(tmp>>8))>>8) */
227dd7cddfSDavid du Colombier
236a9fc400SDavid du Colombier #define MUL(x, y, t) (t = (x)*(y)+128, (t+(t>>8))>>8)
246a9fc400SDavid du Colombier #define MASK13 0xFF00FF00
256a9fc400SDavid du Colombier #define MASK02 0x00FF00FF
266a9fc400SDavid du Colombier #define MUL13(a, x, t) (t = (a)*(((x)&MASK13)>>8)+128, ((t+((t>>8)&MASK02))>>8)&MASK02)
276a9fc400SDavid du Colombier #define MUL02(a, x, t) (t = (a)*(((x)&MASK02)>>0)+128, ((t+((t>>8)&MASK02))>>8)&MASK02)
286a9fc400SDavid du Colombier #define MUL0123(a, x, s, t) ((MUL13(a, x, s)<<8)|MUL02(a, x, t))
296a9fc400SDavid du Colombier
306a9fc400SDavid du Colombier #define MUL2(u, v, x, y) (t = (u)*(v)+(x)*(y)+256, (t+(t>>8))>>8)
316a9fc400SDavid du Colombier
327dd7cddfSDavid du Colombier static void mktables(void);
337dd7cddfSDavid du Colombier typedef int Subdraw(Memdrawparam*);
347dd7cddfSDavid du Colombier static Subdraw chardraw, alphadraw, memoptdraw;
357dd7cddfSDavid du Colombier
367dd7cddfSDavid du Colombier static Memimage* memones;
377dd7cddfSDavid du Colombier static Memimage* memzeros;
387dd7cddfSDavid du Colombier Memimage *memwhite;
397dd7cddfSDavid du Colombier Memimage *memblack;
407dd7cddfSDavid du Colombier Memimage *memtransparent;
417dd7cddfSDavid du Colombier Memimage *memopaque;
427dd7cddfSDavid du Colombier
439a747e4fSDavid du Colombier int _ifmt(Fmt*);
449a747e4fSDavid du Colombier
457dd7cddfSDavid du Colombier void
memimageinit(void)467dd7cddfSDavid du Colombier memimageinit(void)
477dd7cddfSDavid du Colombier {
487dd7cddfSDavid du Colombier static int didinit = 0;
497dd7cddfSDavid du Colombier
507dd7cddfSDavid du Colombier if(didinit)
517dd7cddfSDavid du Colombier return;
527dd7cddfSDavid du Colombier
537dd7cddfSDavid du Colombier didinit = 1;
547dd7cddfSDavid du Colombier
556a9fc400SDavid du Colombier if(strcmp(imagmem->name, "Image") == 0 || strcmp(imagmem->name, "image") == 0)
567dd7cddfSDavid du Colombier imagmem->move = memimagemove;
577dd7cddfSDavid du Colombier
587dd7cddfSDavid du Colombier mktables();
597dd7cddfSDavid du Colombier _memmkcmap();
607dd7cddfSDavid du Colombier
619a747e4fSDavid du Colombier fmtinstall('R', Rfmt);
629a747e4fSDavid du Colombier fmtinstall('P', Pfmt);
639a747e4fSDavid du Colombier fmtinstall('b', _ifmt);
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier memones = allocmemimage(Rect(0,0,1,1), GREY1);
667dd7cddfSDavid du Colombier memones->flags |= Frepl;
677dd7cddfSDavid du Colombier memones->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
687dd7cddfSDavid du Colombier *byteaddr(memones, ZP) = ~0;
697dd7cddfSDavid du Colombier
707dd7cddfSDavid du Colombier memzeros = allocmemimage(Rect(0,0,1,1), GREY1);
717dd7cddfSDavid du Colombier memzeros->flags |= Frepl;
727dd7cddfSDavid du Colombier memzeros->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
737dd7cddfSDavid du Colombier *byteaddr(memzeros, ZP) = 0;
747dd7cddfSDavid du Colombier
757dd7cddfSDavid du Colombier if(memones == nil || memzeros == nil)
767dd7cddfSDavid du Colombier assert(0 /*cannot initialize memimage library */); /* RSC BUG */
777dd7cddfSDavid du Colombier
787dd7cddfSDavid du Colombier memwhite = memones;
797dd7cddfSDavid du Colombier memblack = memzeros;
807dd7cddfSDavid du Colombier memopaque = memones;
817dd7cddfSDavid du Colombier memtransparent = memzeros;
827dd7cddfSDavid du Colombier }
837dd7cddfSDavid du Colombier
847dd7cddfSDavid du Colombier static ulong imgtorgba(Memimage*, ulong);
857dd7cddfSDavid du Colombier static ulong rgbatoimg(Memimage*, ulong);
867dd7cddfSDavid du Colombier static ulong pixelbits(Memimage*, Point);
877dd7cddfSDavid du Colombier
887dd7cddfSDavid du Colombier #define DBG if(0)
897dd7cddfSDavid du Colombier void
memimagedraw(Memimage * dst,Rectangle r,Memimage * src,Point p0,Memimage * mask,Point p1,int op)906a9fc400SDavid du Colombier memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op)
917dd7cddfSDavid du Colombier {
927dd7cddfSDavid du Colombier static int n = 0;
937dd7cddfSDavid du Colombier Memdrawparam par;
947dd7cddfSDavid du Colombier
957dd7cddfSDavid du Colombier if(mask == nil)
967dd7cddfSDavid du Colombier mask = memopaque;
977dd7cddfSDavid du Colombier
9880ee5cbfSDavid du Colombier DBG print("memimagedraw %p/%luX %R @ %p %p/%luX %P %p/%luX %P... ", dst, dst->chan, r, dst->data->bdata, src, src->chan, p0, mask, mask->chan, p1);
997dd7cddfSDavid du Colombier
1007dd7cddfSDavid du Colombier if(drawclip(dst, &r, src, &p0, mask, &p1, &par.sr, &par.mr) == 0){
10159cc4ca5SDavid du Colombier // if(drawdebug)
10259cc4ca5SDavid du Colombier // iprint("empty clipped rectangle\n");
1037dd7cddfSDavid du Colombier return;
1047dd7cddfSDavid du Colombier }
1057dd7cddfSDavid du Colombier
1066a9fc400SDavid du Colombier if(op < Clear || op > SoverD){
1076a9fc400SDavid du Colombier // if(drawdebug)
1086a9fc400SDavid du Colombier // iprint("op out of range: %d\n", op);
1096a9fc400SDavid du Colombier return;
1106a9fc400SDavid du Colombier }
1116a9fc400SDavid du Colombier
1126a9fc400SDavid du Colombier par.op = op;
1137dd7cddfSDavid du Colombier par.dst = dst;
1147dd7cddfSDavid du Colombier par.r = r;
1157dd7cddfSDavid du Colombier par.src = src;
1167dd7cddfSDavid du Colombier /* par.sr set by drawclip */
1177dd7cddfSDavid du Colombier par.mask = mask;
1187dd7cddfSDavid du Colombier /* par.mr set by drawclip */
1197dd7cddfSDavid du Colombier
1207dd7cddfSDavid du Colombier par.state = 0;
1217dd7cddfSDavid du Colombier if(src->flags&Frepl){
1227dd7cddfSDavid du Colombier par.state |= Replsrc;
1237dd7cddfSDavid du Colombier if(Dx(src->r)==1 && Dy(src->r)==1){
1247dd7cddfSDavid du Colombier par.sval = pixelbits(src, src->r.min);
1257dd7cddfSDavid du Colombier par.state |= Simplesrc;
1267dd7cddfSDavid du Colombier par.srgba = imgtorgba(src, par.sval);
1277dd7cddfSDavid du Colombier par.sdval = rgbatoimg(dst, par.srgba);
1286a9fc400SDavid du Colombier if((par.srgba&0xFF) == 0 && (op&DoutS)){
1293ff48bf5SDavid du Colombier // if (drawdebug) iprint("fill with transparent source\n");
1303ff48bf5SDavid du Colombier return; /* no-op successfully handled */
1313ff48bf5SDavid du Colombier }
1327dd7cddfSDavid du Colombier }
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier
1357dd7cddfSDavid du Colombier if(mask->flags & Frepl){
1367dd7cddfSDavid du Colombier par.state |= Replmask;
1377dd7cddfSDavid du Colombier if(Dx(mask->r)==1 && Dy(mask->r)==1){
1387dd7cddfSDavid du Colombier par.mval = pixelbits(mask, mask->r.min);
1396a9fc400SDavid du Colombier if(par.mval == 0 && (op&DoutS)){
14059cc4ca5SDavid du Colombier // if(drawdebug) iprint("fill with zero mask\n");
1417dd7cddfSDavid du Colombier return; /* no-op successfully handled */
1427dd7cddfSDavid du Colombier }
1437dd7cddfSDavid du Colombier par.state |= Simplemask;
1447dd7cddfSDavid du Colombier if(par.mval == ~0)
1457dd7cddfSDavid du Colombier par.state |= Fullmask;
1467dd7cddfSDavid du Colombier par.mrgba = imgtorgba(mask, par.mval);
1477dd7cddfSDavid du Colombier }
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier
15059cc4ca5SDavid du Colombier // if(drawdebug)
15159cc4ca5SDavid du Colombier // iprint("dr %R sr %R mr %R...", r, par.sr, par.mr);
15259cc4ca5SDavid du Colombier DBG print("draw dr %R sr %R mr %R %lux\n", r, par.sr, par.mr, par.state);
1537dd7cddfSDavid du Colombier
1547dd7cddfSDavid du Colombier /*
1557dd7cddfSDavid du Colombier * Now that we've clipped the parameters down to be consistent, we
1567dd7cddfSDavid du Colombier * simply try sub-drawing routines in order until we find one that was able
1577dd7cddfSDavid du Colombier * to handle us. If the sub-drawing routine returns zero, it means it was
1587dd7cddfSDavid du Colombier * unable to satisfy the request, so we do not return.
1597dd7cddfSDavid du Colombier */
1607dd7cddfSDavid du Colombier
1617dd7cddfSDavid du Colombier /*
1627dd7cddfSDavid du Colombier * Hardware support. Each video driver provides this function,
1637dd7cddfSDavid du Colombier * which checks to see if there is anything it can help with.
1647dd7cddfSDavid du Colombier * There could be an if around this checking to see if dst is in video memory.
1657dd7cddfSDavid du Colombier */
16680ee5cbfSDavid du Colombier DBG print("test hwdraw\n");
16759cc4ca5SDavid du Colombier if(hwdraw(&par)){
16859cc4ca5SDavid du Colombier //if(drawdebug) iprint("hw handled\n");
16959cc4ca5SDavid du Colombier DBG print("hwdraw handled\n");
1707dd7cddfSDavid du Colombier return;
1717dd7cddfSDavid du Colombier }
1727dd7cddfSDavid du Colombier /*
1737dd7cddfSDavid du Colombier * Optimizations using memmove and memset.
1747dd7cddfSDavid du Colombier */
17580ee5cbfSDavid du Colombier DBG print("test memoptdraw\n");
1767dd7cddfSDavid du Colombier if(memoptdraw(&par)){
17759cc4ca5SDavid du Colombier //if(drawdebug) iprint("memopt handled\n");
17859cc4ca5SDavid du Colombier DBG print("memopt handled\n");
1797dd7cddfSDavid du Colombier return;
1807dd7cddfSDavid du Colombier }
1817dd7cddfSDavid du Colombier
1827dd7cddfSDavid du Colombier /*
1837dd7cddfSDavid du Colombier * Character drawing.
1847dd7cddfSDavid du Colombier * Solid source color being painted through a boolean mask onto a high res image.
1857dd7cddfSDavid du Colombier */
18680ee5cbfSDavid du Colombier DBG print("test chardraw\n");
1877dd7cddfSDavid du Colombier if(chardraw(&par)){
18859cc4ca5SDavid du Colombier //if(drawdebug) iprint("chardraw handled\n");
18959cc4ca5SDavid du Colombier DBG print("chardraw handled\n");
1907dd7cddfSDavid du Colombier return;
1917dd7cddfSDavid du Colombier }
1927dd7cddfSDavid du Colombier
1937dd7cddfSDavid du Colombier /*
1947dd7cddfSDavid du Colombier * General calculation-laden case that does alpha for each pixel.
1957dd7cddfSDavid du Colombier */
19680ee5cbfSDavid du Colombier DBG print("do alphadraw\n");
1977dd7cddfSDavid du Colombier alphadraw(&par);
19859cc4ca5SDavid du Colombier //if(drawdebug) iprint("alphadraw handled\n");
19959cc4ca5SDavid du Colombier DBG print("alphadraw handled\n");
2007dd7cddfSDavid du Colombier }
2017dd7cddfSDavid du Colombier #undef DBG
2027dd7cddfSDavid du Colombier
2037dd7cddfSDavid du Colombier /*
2047dd7cddfSDavid du Colombier * Clip the destination rectangle further based on the properties of the
2057dd7cddfSDavid du Colombier * source and mask rectangles. Once the destination rectangle is properly
2067dd7cddfSDavid du Colombier * clipped, adjust the source and mask rectangles to be the same size.
2077dd7cddfSDavid du Colombier * Then if source or mask is replicated, move its clipped rectangle
2087dd7cddfSDavid du Colombier * so that its minimum point falls within the repl rectangle.
2097dd7cddfSDavid du Colombier *
2107dd7cddfSDavid du Colombier * Return zero if the final rectangle is null.
2117dd7cddfSDavid du Colombier */
2127dd7cddfSDavid du Colombier int
drawclip(Memimage * dst,Rectangle * r,Memimage * src,Point * p0,Memimage * mask,Point * p1,Rectangle * sr,Rectangle * mr)2137dd7cddfSDavid du Colombier drawclip(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask, Point *p1, Rectangle *sr, Rectangle *mr)
2147dd7cddfSDavid du Colombier {
2157dd7cddfSDavid du Colombier Point rmin, delta;
2167dd7cddfSDavid du Colombier int splitcoords;
2177dd7cddfSDavid du Colombier Rectangle omr;
2187dd7cddfSDavid du Colombier
2197dd7cddfSDavid du Colombier if(r->min.x>=r->max.x || r->min.y>=r->max.y)
2207dd7cddfSDavid du Colombier return 0;
2217dd7cddfSDavid du Colombier splitcoords = (p0->x!=p1->x) || (p0->y!=p1->y);
2227dd7cddfSDavid du Colombier /* clip to destination */
2237dd7cddfSDavid du Colombier rmin = r->min;
2247dd7cddfSDavid du Colombier if(!rectclip(r, dst->r) || !rectclip(r, dst->clipr))
2257dd7cddfSDavid du Colombier return 0;
2267dd7cddfSDavid du Colombier /* move mask point */
2277dd7cddfSDavid du Colombier p1->x += r->min.x-rmin.x;
2287dd7cddfSDavid du Colombier p1->y += r->min.y-rmin.y;
2297dd7cddfSDavid du Colombier /* move source point */
2307dd7cddfSDavid du Colombier p0->x += r->min.x-rmin.x;
2317dd7cddfSDavid du Colombier p0->y += r->min.y-rmin.y;
2327dd7cddfSDavid du Colombier /* map destination rectangle into source */
2337dd7cddfSDavid du Colombier sr->min = *p0;
2347dd7cddfSDavid du Colombier sr->max.x = p0->x+Dx(*r);
2357dd7cddfSDavid du Colombier sr->max.y = p0->y+Dy(*r);
2367dd7cddfSDavid du Colombier /* sr is r in source coordinates; clip to source */
2377dd7cddfSDavid du Colombier if(!(src->flags&Frepl) && !rectclip(sr, src->r))
2387dd7cddfSDavid du Colombier return 0;
2397dd7cddfSDavid du Colombier if(!rectclip(sr, src->clipr))
2407dd7cddfSDavid du Colombier return 0;
2417dd7cddfSDavid du Colombier /* compute and clip rectangle in mask */
2427dd7cddfSDavid du Colombier if(splitcoords){
2437dd7cddfSDavid du Colombier /* move mask point with source */
2447dd7cddfSDavid du Colombier p1->x += sr->min.x-p0->x;
2457dd7cddfSDavid du Colombier p1->y += sr->min.y-p0->y;
2467dd7cddfSDavid du Colombier mr->min = *p1;
2477dd7cddfSDavid du Colombier mr->max.x = p1->x+Dx(*sr);
2487dd7cddfSDavid du Colombier mr->max.y = p1->y+Dy(*sr);
2497dd7cddfSDavid du Colombier omr = *mr;
2507dd7cddfSDavid du Colombier /* mr is now rectangle in mask; clip it */
2517dd7cddfSDavid du Colombier if(!(mask->flags&Frepl) && !rectclip(mr, mask->r))
2527dd7cddfSDavid du Colombier return 0;
2537dd7cddfSDavid du Colombier if(!rectclip(mr, mask->clipr))
2547dd7cddfSDavid du Colombier return 0;
2557dd7cddfSDavid du Colombier /* reflect any clips back to source */
2567dd7cddfSDavid du Colombier sr->min.x += mr->min.x-omr.min.x;
2577dd7cddfSDavid du Colombier sr->min.y += mr->min.y-omr.min.y;
2587dd7cddfSDavid du Colombier sr->max.x += mr->max.x-omr.max.x;
2597dd7cddfSDavid du Colombier sr->max.y += mr->max.y-omr.max.y;
2607dd7cddfSDavid du Colombier *p1 = mr->min;
2617dd7cddfSDavid du Colombier }else{
2627dd7cddfSDavid du Colombier if(!(mask->flags&Frepl) && !rectclip(sr, mask->r))
2637dd7cddfSDavid du Colombier return 0;
2647dd7cddfSDavid du Colombier if(!rectclip(sr, mask->clipr))
2657dd7cddfSDavid du Colombier return 0;
2667dd7cddfSDavid du Colombier *p1 = sr->min;
2677dd7cddfSDavid du Colombier }
2687dd7cddfSDavid du Colombier
2697dd7cddfSDavid du Colombier /* move source clipping back to destination */
2707dd7cddfSDavid du Colombier delta.x = r->min.x - p0->x;
2717dd7cddfSDavid du Colombier delta.y = r->min.y - p0->y;
2727dd7cddfSDavid du Colombier r->min.x = sr->min.x + delta.x;
2737dd7cddfSDavid du Colombier r->min.y = sr->min.y + delta.y;
2747dd7cddfSDavid du Colombier r->max.x = sr->max.x + delta.x;
2757dd7cddfSDavid du Colombier r->max.y = sr->max.y + delta.y;
2767dd7cddfSDavid du Colombier
2777dd7cddfSDavid du Colombier /* move source rectangle so sr->min is in src->r */
2787dd7cddfSDavid du Colombier if(src->flags&Frepl) {
2797dd7cddfSDavid du Colombier delta.x = drawreplxy(src->r.min.x, src->r.max.x, sr->min.x) - sr->min.x;
2807dd7cddfSDavid du Colombier delta.y = drawreplxy(src->r.min.y, src->r.max.y, sr->min.y) - sr->min.y;
2817dd7cddfSDavid du Colombier sr->min.x += delta.x;
2827dd7cddfSDavid du Colombier sr->min.y += delta.y;
2837dd7cddfSDavid du Colombier sr->max.x += delta.x;
2847dd7cddfSDavid du Colombier sr->max.y += delta.y;
2857dd7cddfSDavid du Colombier }
2867dd7cddfSDavid du Colombier *p0 = sr->min;
2877dd7cddfSDavid du Colombier
2887dd7cddfSDavid du Colombier /* move mask point so it is in mask->r */
2897dd7cddfSDavid du Colombier *p1 = drawrepl(mask->r, *p1);
2907dd7cddfSDavid du Colombier mr->min = *p1;
2917dd7cddfSDavid du Colombier mr->max.x = p1->x+Dx(*sr);
2927dd7cddfSDavid du Colombier mr->max.y = p1->y+Dy(*sr);
2937dd7cddfSDavid du Colombier
2947dd7cddfSDavid du Colombier assert(Dx(*sr) == Dx(*mr) && Dx(*mr) == Dx(*r));
2957dd7cddfSDavid du Colombier assert(Dy(*sr) == Dy(*mr) && Dy(*mr) == Dy(*r));
2967dd7cddfSDavid du Colombier assert(ptinrect(*p0, src->r));
2977dd7cddfSDavid du Colombier assert(ptinrect(*p1, mask->r));
2987dd7cddfSDavid du Colombier assert(ptinrect(r->min, dst->r));
2997dd7cddfSDavid du Colombier
3007dd7cddfSDavid du Colombier return 1;
3017dd7cddfSDavid du Colombier }
3027dd7cddfSDavid du Colombier
3037dd7cddfSDavid du Colombier /*
3047dd7cddfSDavid du Colombier * Conversion tables.
3057dd7cddfSDavid du Colombier */
3067dd7cddfSDavid du Colombier static uchar replbit[1+8][256]; /* replbit[x][y] is the replication of the x-bit quantity y to 8-bit depth */
3077dd7cddfSDavid du Colombier static uchar conv18[256][8]; /* conv18[x][y] is the yth pixel in the depth-1 pixel x */
3087dd7cddfSDavid du Colombier static uchar conv28[256][4]; /* ... */
3097dd7cddfSDavid du Colombier static uchar conv48[256][2];
3107dd7cddfSDavid du Colombier
3117dd7cddfSDavid du Colombier /*
3127dd7cddfSDavid du Colombier * bitmap of how to replicate n bits to fill 8, for 1 ≤ n ≤ 8.
3137dd7cddfSDavid du Colombier * the X's are where to put the bottom (ones) bit of the n-bit pattern.
3147dd7cddfSDavid du Colombier * only the top 8 bits of the result are actually used.
3157dd7cddfSDavid du Colombier * (the lower 8 bits are needed to get bits in the right place
3167dd7cddfSDavid du Colombier * when n is not a divisor of 8.)
3177dd7cddfSDavid du Colombier *
3187dd7cddfSDavid du Colombier * Should check to see if its easier to just refer to replmul than
3197dd7cddfSDavid du Colombier * use the precomputed values in replbit. On PCs it may well
3207dd7cddfSDavid du Colombier * be; on machines with slow multiply instructions it probably isn't.
3217dd7cddfSDavid du Colombier */
3227dd7cddfSDavid du Colombier #define a ((((((((((((((((0
3237dd7cddfSDavid du Colombier #define X *2+1)
3247dd7cddfSDavid du Colombier #define _ *2)
3257dd7cddfSDavid du Colombier static int replmul[1+8] = {
3267dd7cddfSDavid du Colombier 0,
3277dd7cddfSDavid du Colombier a X X X X X X X X X X X X X X X X,
3287dd7cddfSDavid du Colombier a _ X _ X _ X _ X _ X _ X _ X _ X,
3297dd7cddfSDavid du Colombier a _ _ X _ _ X _ _ X _ _ X _ _ X _,
3307dd7cddfSDavid du Colombier a _ _ _ X _ _ _ X _ _ _ X _ _ _ X,
3317dd7cddfSDavid du Colombier a _ _ _ _ X _ _ _ _ X _ _ _ _ X _,
3327dd7cddfSDavid du Colombier a _ _ _ _ _ X _ _ _ _ _ X _ _ _ _,
3337dd7cddfSDavid du Colombier a _ _ _ _ _ _ X _ _ _ _ _ _ X _ _,
3347dd7cddfSDavid du Colombier a _ _ _ _ _ _ _ X _ _ _ _ _ _ _ X,
3357dd7cddfSDavid du Colombier };
3367dd7cddfSDavid du Colombier #undef a
3377dd7cddfSDavid du Colombier #undef X
3387dd7cddfSDavid du Colombier #undef _
3397dd7cddfSDavid du Colombier
3407dd7cddfSDavid du Colombier static void
mktables(void)3417dd7cddfSDavid du Colombier mktables(void)
3427dd7cddfSDavid du Colombier {
3437dd7cddfSDavid du Colombier int i, j, mask, sh, small;
3447dd7cddfSDavid du Colombier
3457dd7cddfSDavid du Colombier if(tablesbuilt)
3467dd7cddfSDavid du Colombier return;
3477dd7cddfSDavid du Colombier
3489a747e4fSDavid du Colombier fmtinstall('R', Rfmt);
3499a747e4fSDavid du Colombier fmtinstall('P', Pfmt);
3507dd7cddfSDavid du Colombier tablesbuilt = 1;
3516a9fc400SDavid du Colombier
3527dd7cddfSDavid du Colombier /* bit replication up to 8 bits */
3537dd7cddfSDavid du Colombier for(i=0; i<256; i++){
3547dd7cddfSDavid du Colombier for(j=0; j<=8; j++){ /* j <= 8 [sic] */
3557dd7cddfSDavid du Colombier small = i & ((1<<j)-1);
3567dd7cddfSDavid du Colombier replbit[j][i] = (small*replmul[j])>>8;
3577dd7cddfSDavid du Colombier }
3587dd7cddfSDavid du Colombier }
3597dd7cddfSDavid du Colombier
3607dd7cddfSDavid du Colombier /* bit unpacking up to 8 bits, only powers of 2 */
3617dd7cddfSDavid du Colombier for(i=0; i<256; i++){
3627dd7cddfSDavid du Colombier for(j=0, sh=7, mask=1; j<8; j++, sh--)
3637dd7cddfSDavid du Colombier conv18[i][j] = replbit[1][(i>>sh)&mask];
3647dd7cddfSDavid du Colombier
3657dd7cddfSDavid du Colombier for(j=0, sh=6, mask=3; j<4; j++, sh-=2)
3667dd7cddfSDavid du Colombier conv28[i][j] = replbit[2][(i>>sh)&mask];
3677dd7cddfSDavid du Colombier
3687dd7cddfSDavid du Colombier for(j=0, sh=4, mask=15; j<2; j++, sh-=4)
3697dd7cddfSDavid du Colombier conv48[i][j] = replbit[4][(i>>sh)&mask];
3707dd7cddfSDavid du Colombier }
3717dd7cddfSDavid du Colombier }
3727dd7cddfSDavid du Colombier
3736a9fc400SDavid du Colombier static uchar ones = 0xff;
3746a9fc400SDavid du Colombier
3757dd7cddfSDavid du Colombier /*
3767dd7cddfSDavid du Colombier * General alpha drawing case. Can handle anything.
3777dd7cddfSDavid du Colombier */
3786a9fc400SDavid du Colombier typedef struct Buffer Buffer;
3796a9fc400SDavid du Colombier struct Buffer {
3806a9fc400SDavid du Colombier /* used by most routines */
3817dd7cddfSDavid du Colombier uchar *red;
3827dd7cddfSDavid du Colombier uchar *grn;
3837dd7cddfSDavid du Colombier uchar *blu;
3847dd7cddfSDavid du Colombier uchar *alpha;
3857dd7cddfSDavid du Colombier uchar *grey;
3866a9fc400SDavid du Colombier ulong *rgba;
3877dd7cddfSDavid du Colombier int delta; /* number of bytes to add to pointer to get next pixel to the right */
3886a9fc400SDavid du Colombier
3896a9fc400SDavid du Colombier /* used by boolcalc* for mask data */
3907dd7cddfSDavid du Colombier uchar *m; /* ptr to mask data r.min byte; like p->bytermin */
3917dd7cddfSDavid du Colombier int mskip; /* no. of left bits to skip in *m */
3927dd7cddfSDavid du Colombier uchar *bm; /* ptr to mask data img->r.min byte; like p->bytey0s */
3937dd7cddfSDavid du Colombier int bmskip; /* no. of left bits to skip in *bm */
3947dd7cddfSDavid du Colombier uchar *em; /* ptr to mask data img->r.max.x byte; like p->bytey0e */
3957dd7cddfSDavid du Colombier int emskip; /* no. of right bits to skip in *em */
3967dd7cddfSDavid du Colombier };
3977dd7cddfSDavid du Colombier
3987dd7cddfSDavid du Colombier typedef struct Param Param;
3997dd7cddfSDavid du Colombier typedef Buffer Readfn(Param*, uchar*, int);
4007dd7cddfSDavid du Colombier typedef void Writefn(Param*, uchar*, Buffer);
4016a9fc400SDavid du Colombier typedef Buffer Calcfn(Buffer, Buffer, Buffer, int, int, int);
4027dd7cddfSDavid du Colombier
4037dd7cddfSDavid du Colombier enum {
4047dd7cddfSDavid du Colombier MAXBCACHE = 16
4057dd7cddfSDavid du Colombier };
4067dd7cddfSDavid du Colombier
4077dd7cddfSDavid du Colombier /* giant rathole to customize functions with */
4087dd7cddfSDavid du Colombier struct Param {
4097dd7cddfSDavid du Colombier Readfn *replcall;
4107dd7cddfSDavid du Colombier Readfn *greymaskcall;
4117dd7cddfSDavid du Colombier Readfn *convreadcall;
4127dd7cddfSDavid du Colombier Writefn *convwritecall;
4137dd7cddfSDavid du Colombier
4147dd7cddfSDavid du Colombier Memimage *img;
4157dd7cddfSDavid du Colombier Rectangle r;
4167dd7cddfSDavid du Colombier int dx; /* of r */
4177dd7cddfSDavid du Colombier int needbuf;
4187dd7cddfSDavid du Colombier int convgrey;
4197dd7cddfSDavid du Colombier int alphaonly;
4207dd7cddfSDavid du Colombier
4217dd7cddfSDavid du Colombier uchar *bytey0s; /* byteaddr(Pt(img->r.min.x, img->r.min.y)) */
4227dd7cddfSDavid du Colombier uchar *bytermin; /* byteaddr(Pt(r.min.x, img->r.min.y)) */
4237dd7cddfSDavid du Colombier uchar *bytey0e; /* byteaddr(Pt(img->r.max.x, img->r.min.y)) */
4247dd7cddfSDavid du Colombier int bwidth;
4257dd7cddfSDavid du Colombier
4267dd7cddfSDavid du Colombier int replcache; /* if set, cache buffers */
4277dd7cddfSDavid du Colombier Buffer bcache[MAXBCACHE];
4287dd7cddfSDavid du Colombier ulong bfilled;
4297dd7cddfSDavid du Colombier uchar *bufbase;
4307dd7cddfSDavid du Colombier int bufoff;
4317dd7cddfSDavid du Colombier int bufdelta;
4327dd7cddfSDavid du Colombier
4337dd7cddfSDavid du Colombier int dir;
4347dd7cddfSDavid du Colombier
4357dd7cddfSDavid du Colombier int convbufoff;
4367dd7cddfSDavid du Colombier uchar *convbuf;
4377dd7cddfSDavid du Colombier Param *convdpar;
4387dd7cddfSDavid du Colombier int convdx;
4397dd7cddfSDavid du Colombier };
4407dd7cddfSDavid du Colombier
4417dd7cddfSDavid du Colombier static uchar *drawbuf;
4427dd7cddfSDavid du Colombier static int ndrawbuf;
4437dd7cddfSDavid du Colombier static int mdrawbuf;
4447dd7cddfSDavid du Colombier static Readfn greymaskread, replread, readptr;
4457dd7cddfSDavid du Colombier static Writefn nullwrite;
4466a9fc400SDavid du Colombier static Calcfn alphacalc0, alphacalc14, alphacalc2810, alphacalc3679, alphacalc5, alphacalc11, alphacalcS;
4476a9fc400SDavid du Colombier static Calcfn boolcalc14, boolcalc236789, boolcalc1011;
4487dd7cddfSDavid du Colombier
4497dd7cddfSDavid du Colombier static Readfn* readfn(Memimage*);
4507dd7cddfSDavid du Colombier static Readfn* readalphafn(Memimage*);
4517dd7cddfSDavid du Colombier static Writefn* writefn(Memimage*);
4527dd7cddfSDavid du Colombier
4537dd7cddfSDavid du Colombier static Calcfn* boolcopyfn(Memimage*, Memimage*);
454*2c1878b4SDavid du Colombier static Readfn* convfn(Memimage*, Param*, Memimage*, Param*, int*);
4557dd7cddfSDavid du Colombier static Readfn* ptrfn(Memimage*);
4567dd7cddfSDavid du Colombier
4576a9fc400SDavid du Colombier static Calcfn *alphacalc[Ncomp] =
4586a9fc400SDavid du Colombier {
4596a9fc400SDavid du Colombier alphacalc0, /* Clear */
4606a9fc400SDavid du Colombier alphacalc14, /* DoutS */
4616a9fc400SDavid du Colombier alphacalc2810, /* SoutD */
4626a9fc400SDavid du Colombier alphacalc3679, /* DxorS */
4636a9fc400SDavid du Colombier alphacalc14, /* DinS */
4646a9fc400SDavid du Colombier alphacalc5, /* D */
4656a9fc400SDavid du Colombier alphacalc3679, /* DatopS */
4666a9fc400SDavid du Colombier alphacalc3679, /* DoverS */
4676a9fc400SDavid du Colombier alphacalc2810, /* SinD */
4686a9fc400SDavid du Colombier alphacalc3679, /* SatopD */
4696a9fc400SDavid du Colombier alphacalc2810, /* S */
4706a9fc400SDavid du Colombier alphacalc11, /* SoverD */
4716a9fc400SDavid du Colombier };
4726a9fc400SDavid du Colombier
4736a9fc400SDavid du Colombier static Calcfn *boolcalc[Ncomp] =
4746a9fc400SDavid du Colombier {
4756a9fc400SDavid du Colombier alphacalc0, /* Clear */
4766a9fc400SDavid du Colombier boolcalc14, /* DoutS */
4776a9fc400SDavid du Colombier boolcalc236789, /* SoutD */
4786a9fc400SDavid du Colombier boolcalc236789, /* DxorS */
4796a9fc400SDavid du Colombier boolcalc14, /* DinS */
4806a9fc400SDavid du Colombier alphacalc5, /* D */
4816a9fc400SDavid du Colombier boolcalc236789, /* DatopS */
4826a9fc400SDavid du Colombier boolcalc236789, /* DoverS */
4836a9fc400SDavid du Colombier boolcalc236789, /* SinD */
4846a9fc400SDavid du Colombier boolcalc236789, /* SatopD */
4856a9fc400SDavid du Colombier boolcalc1011, /* S */
4866a9fc400SDavid du Colombier boolcalc1011, /* SoverD */
4876a9fc400SDavid du Colombier };
4886a9fc400SDavid du Colombier
489*2c1878b4SDavid du Colombier /*
490*2c1878b4SDavid du Colombier * Avoid standard Lock, QLock so that can be used in kernel.
491*2c1878b4SDavid du Colombier */
492*2c1878b4SDavid du Colombier typedef struct Dbuf Dbuf;
493*2c1878b4SDavid du Colombier struct Dbuf
4947dd7cddfSDavid du Colombier {
4957dd7cddfSDavid du Colombier uchar *p;
496*2c1878b4SDavid du Colombier int n;
497*2c1878b4SDavid du Colombier Param spar, mpar, dpar;
498*2c1878b4SDavid du Colombier int inuse;
499*2c1878b4SDavid du Colombier };
500*2c1878b4SDavid du Colombier static Dbuf dbuf[10];
5017dd7cddfSDavid du Colombier
502*2c1878b4SDavid du Colombier static Dbuf*
allocdbuf(void)503*2c1878b4SDavid du Colombier allocdbuf(void)
5047dd7cddfSDavid du Colombier {
505*2c1878b4SDavid du Colombier int i;
506*2c1878b4SDavid du Colombier
507*2c1878b4SDavid du Colombier for(i=0; i<nelem(dbuf); i++){
508*2c1878b4SDavid du Colombier if(dbuf[i].inuse)
509*2c1878b4SDavid du Colombier continue;
510*2c1878b4SDavid du Colombier if(!_tas(&dbuf[i].inuse))
511*2c1878b4SDavid du Colombier return &dbuf[i];
512*2c1878b4SDavid du Colombier }
513*2c1878b4SDavid du Colombier return nil;
514*2c1878b4SDavid du Colombier }
515*2c1878b4SDavid du Colombier
516*2c1878b4SDavid du Colombier static void
getparam(Param * p,Memimage * img,Rectangle r,int convgrey,int needbuf,int * ndrawbuf)517*2c1878b4SDavid du Colombier getparam(Param *p, Memimage *img, Rectangle r, int convgrey, int needbuf, int *ndrawbuf)
518*2c1878b4SDavid du Colombier {
5197dd7cddfSDavid du Colombier int nbuf;
5207dd7cddfSDavid du Colombier
521*2c1878b4SDavid du Colombier memset(p, 0, sizeof *p);
5227dd7cddfSDavid du Colombier
523*2c1878b4SDavid du Colombier p->img = img;
524*2c1878b4SDavid du Colombier p->r = r;
525*2c1878b4SDavid du Colombier p->dx = Dx(r);
526*2c1878b4SDavid du Colombier p->needbuf = needbuf;
527*2c1878b4SDavid du Colombier p->convgrey = convgrey;
5287dd7cddfSDavid du Colombier
5297dd7cddfSDavid du Colombier assert(img->r.min.x <= r.min.x && r.min.x < img->r.max.x);
5307dd7cddfSDavid du Colombier
531*2c1878b4SDavid du Colombier p->bytey0s = byteaddr(img, Pt(img->r.min.x, img->r.min.y));
532*2c1878b4SDavid du Colombier p->bytermin = byteaddr(img, Pt(r.min.x, img->r.min.y));
533*2c1878b4SDavid du Colombier p->bytey0e = byteaddr(img, Pt(img->r.max.x, img->r.min.y));
534*2c1878b4SDavid du Colombier p->bwidth = sizeof(ulong)*img->width;
5357dd7cddfSDavid du Colombier
536*2c1878b4SDavid du Colombier assert(p->bytey0s <= p->bytermin && p->bytermin <= p->bytey0e);
5377dd7cddfSDavid du Colombier
538*2c1878b4SDavid du Colombier if(p->r.min.x == p->img->r.min.x)
539*2c1878b4SDavid du Colombier assert(p->bytermin == p->bytey0s);
5407dd7cddfSDavid du Colombier
5417dd7cddfSDavid du Colombier nbuf = 1;
5427dd7cddfSDavid du Colombier if((img->flags&Frepl) && Dy(img->r) <= MAXBCACHE && Dy(img->r) < Dy(r)){
543*2c1878b4SDavid du Colombier p->replcache = 1;
5447dd7cddfSDavid du Colombier nbuf = Dy(img->r);
5457dd7cddfSDavid du Colombier }
546*2c1878b4SDavid du Colombier p->bufdelta = 4*p->dx;
547*2c1878b4SDavid du Colombier p->bufoff = *ndrawbuf;
548*2c1878b4SDavid du Colombier *ndrawbuf += p->bufdelta*nbuf;
5497dd7cddfSDavid du Colombier }
5507dd7cddfSDavid du Colombier
5517dd7cddfSDavid du Colombier static void
clipy(Memimage * img,int * y)5527dd7cddfSDavid du Colombier clipy(Memimage *img, int *y)
5537dd7cddfSDavid du Colombier {
5547dd7cddfSDavid du Colombier int dy;
5557dd7cddfSDavid du Colombier
5567dd7cddfSDavid du Colombier dy = Dy(img->r);
5577dd7cddfSDavid du Colombier if(*y == dy)
5587dd7cddfSDavid du Colombier *y = 0;
5597dd7cddfSDavid du Colombier else if(*y == -1)
5607dd7cddfSDavid du Colombier *y = dy-1;
5617dd7cddfSDavid du Colombier assert(0 <= *y && *y < dy);
5627dd7cddfSDavid du Colombier }
5637dd7cddfSDavid du Colombier
5647dd7cddfSDavid du Colombier static void
dumpbuf(char * s,Buffer b,int n)5657dd7cddfSDavid du Colombier dumpbuf(char *s, Buffer b, int n)
5667dd7cddfSDavid du Colombier {
5677dd7cddfSDavid du Colombier int i;
5687dd7cddfSDavid du Colombier uchar *p;
5697dd7cddfSDavid du Colombier
5707dd7cddfSDavid du Colombier print("%s", s);
5717dd7cddfSDavid du Colombier for(i=0; i<n; i++){
5727dd7cddfSDavid du Colombier print(" ");
5737dd7cddfSDavid du Colombier if(p=b.grey){
5747dd7cddfSDavid du Colombier print(" k%.2uX", *p);
5757dd7cddfSDavid du Colombier b.grey += b.delta;
5767dd7cddfSDavid du Colombier }else{
5777dd7cddfSDavid du Colombier if(p=b.red){
5787dd7cddfSDavid du Colombier print(" r%.2uX", *p);
5797dd7cddfSDavid du Colombier b.red += b.delta;
5807dd7cddfSDavid du Colombier }
5817dd7cddfSDavid du Colombier if(p=b.grn){
5827dd7cddfSDavid du Colombier print(" g%.2uX", *p);
5837dd7cddfSDavid du Colombier b.grn += b.delta;
5847dd7cddfSDavid du Colombier }
5857dd7cddfSDavid du Colombier if(p=b.blu){
5867dd7cddfSDavid du Colombier print(" b%.2uX", *p);
5877dd7cddfSDavid du Colombier b.blu += b.delta;
5887dd7cddfSDavid du Colombier }
5897dd7cddfSDavid du Colombier }
5906a9fc400SDavid du Colombier if((p=b.alpha) != &ones){
5917dd7cddfSDavid du Colombier print(" α%.2uX", *p);
5927dd7cddfSDavid du Colombier b.alpha += b.delta;
5937dd7cddfSDavid du Colombier }
5947dd7cddfSDavid du Colombier }
5957dd7cddfSDavid du Colombier print("\n");
5967dd7cddfSDavid du Colombier }
5977dd7cddfSDavid du Colombier
5987dd7cddfSDavid du Colombier /*
5997dd7cddfSDavid du Colombier * For each scan line, we expand the pixels from source, mask, and destination
6007dd7cddfSDavid du Colombier * into byte-aligned red, green, blue, alpha, and grey channels. If buffering is not
6017dd7cddfSDavid du Colombier * needed and the channels were already byte-aligned (grey8, rgb24, rgba32, rgb32),
6027dd7cddfSDavid du Colombier * the readers need not copy the data: they can simply return pointers to the data.
6037dd7cddfSDavid du Colombier * If the destination image is grey and the source is not, it is converted using the NTSC
6047dd7cddfSDavid du Colombier * formula.
6057dd7cddfSDavid du Colombier *
6067dd7cddfSDavid du Colombier * Once we have all the channels, we call either rgbcalc or greycalc, depending on
6077dd7cddfSDavid du Colombier * whether the destination image is color. This is allowed to overwrite the dst buffer (perhaps
6087dd7cddfSDavid du Colombier * the actual data, perhaps a copy) with its result. It should only overwrite the dst buffer
6097dd7cddfSDavid du Colombier * with the same format (i.e. red bytes with red bytes, etc.) A new buffer is returned from
6107dd7cddfSDavid du Colombier * the calculator, and that buffer is passed to a function to write it to the destination.
6117dd7cddfSDavid du Colombier * If the buffer is already pointing at the destination, the writing function is a no-op.
6127dd7cddfSDavid du Colombier */
6137dd7cddfSDavid du Colombier #define DBG if(0)
6147dd7cddfSDavid du Colombier static int
alphadraw(Memdrawparam * par)6157dd7cddfSDavid du Colombier alphadraw(Memdrawparam *par)
6167dd7cddfSDavid du Colombier {
6176a9fc400SDavid du Colombier int isgrey, starty, endy, op;
6187dd7cddfSDavid du Colombier int needbuf, dsty, srcy, masky;
619*2c1878b4SDavid du Colombier int y, dir, dx, dy, ndrawbuf;
620*2c1878b4SDavid du Colombier uchar *drawbuf;
6217dd7cddfSDavid du Colombier Buffer bsrc, bdst, bmask;
6227dd7cddfSDavid du Colombier Readfn *rdsrc, *rdmask, *rddst;
6237dd7cddfSDavid du Colombier Calcfn *calc;
6247dd7cddfSDavid du Colombier Writefn *wrdst;
6257dd7cddfSDavid du Colombier Memimage *src, *mask, *dst;
6267dd7cddfSDavid du Colombier Rectangle r, sr, mr;
627*2c1878b4SDavid du Colombier Dbuf *z;
6287dd7cddfSDavid du Colombier
6297dd7cddfSDavid du Colombier r = par->r;
6307dd7cddfSDavid du Colombier dx = Dx(r);
6317dd7cddfSDavid du Colombier dy = Dy(r);
6327dd7cddfSDavid du Colombier
633*2c1878b4SDavid du Colombier z = allocdbuf();
634*2c1878b4SDavid du Colombier if(z == nil)
635*2c1878b4SDavid du Colombier return 0;
6367dd7cddfSDavid du Colombier
6377dd7cddfSDavid du Colombier src = par->src;
6387dd7cddfSDavid du Colombier mask = par->mask;
6397dd7cddfSDavid du Colombier dst = par->dst;
6407dd7cddfSDavid du Colombier sr = par->sr;
6417dd7cddfSDavid du Colombier mr = par->mr;
6426a9fc400SDavid du Colombier op = par->op;
6437dd7cddfSDavid du Colombier
6447dd7cddfSDavid du Colombier isgrey = dst->flags&Fgrey;
6457dd7cddfSDavid du Colombier
6467dd7cddfSDavid du Colombier /*
6477dd7cddfSDavid du Colombier * Buffering when src and dst are the same bitmap is sufficient but not
6487dd7cddfSDavid du Colombier * necessary. There are stronger conditions we could use. We could
6497dd7cddfSDavid du Colombier * check to see if the rectangles intersect, and if simply moving in the
6507dd7cddfSDavid du Colombier * correct y direction can avoid the need to buffer.
6517dd7cddfSDavid du Colombier */
6527dd7cddfSDavid du Colombier needbuf = (src->data == dst->data);
6537dd7cddfSDavid du Colombier
654*2c1878b4SDavid du Colombier ndrawbuf = 0;
655*2c1878b4SDavid du Colombier getparam(&z->spar, src, sr, isgrey, needbuf, &ndrawbuf);
656*2c1878b4SDavid du Colombier getparam(&z->dpar, dst, r, isgrey, needbuf, &ndrawbuf);
657*2c1878b4SDavid du Colombier getparam(&z->mpar, mask, mr, 0, needbuf, &ndrawbuf);
6587dd7cddfSDavid du Colombier
6597dd7cddfSDavid du Colombier dir = (needbuf && byteaddr(dst, r.min) > byteaddr(src, sr.min)) ? -1 : 1;
660*2c1878b4SDavid du Colombier z->spar.dir = z->mpar.dir = z->dpar.dir = dir;
6617dd7cddfSDavid du Colombier
6627dd7cddfSDavid du Colombier /*
6637dd7cddfSDavid du Colombier * If the mask is purely boolean, we can convert from src to dst format
6647dd7cddfSDavid du Colombier * when we read src, and then just copy it to dst where the mask tells us to.
6657dd7cddfSDavid du Colombier * This requires a boolean (1-bit grey) mask and lack of a source alpha channel.
6667dd7cddfSDavid du Colombier *
6677dd7cddfSDavid du Colombier * The computation is accomplished by assigning the function pointers as follows:
6687dd7cddfSDavid du Colombier * rdsrc - read and convert source into dst format in a buffer
6697dd7cddfSDavid du Colombier * rdmask - convert mask to bytes, set pointer to it
6707dd7cddfSDavid du Colombier * rddst - fill with pointer to real dst data, but do no reads
6717dd7cddfSDavid du Colombier * calc - copy src onto dst when mask says to.
6727dd7cddfSDavid du Colombier * wrdst - do nothing
6737dd7cddfSDavid du Colombier * This is slightly sleazy, since things aren't doing exactly what their names say,
6747dd7cddfSDavid du Colombier * but it avoids a fair amount of code duplication to make this a case here
6757dd7cddfSDavid du Colombier * rather than have a separate booldraw.
6767dd7cddfSDavid du Colombier */
6777dd7cddfSDavid du Colombier //if(drawdebug) iprint("flag %lud mchan %lux=?%x dd %d\n", src->flags&Falpha, mask->chan, GREY1, dst->depth);
6786a9fc400SDavid du Colombier if(!(src->flags&Falpha) && mask->chan == GREY1 && dst->depth >= 8 && op == SoverD){
6797dd7cddfSDavid du Colombier //if(drawdebug) iprint("boolcopy...");
680*2c1878b4SDavid du Colombier rdsrc = convfn(dst, &z->dpar, src, &z->spar, &ndrawbuf);
6817dd7cddfSDavid du Colombier rddst = readptr;
6827dd7cddfSDavid du Colombier rdmask = readfn(mask);
6837dd7cddfSDavid du Colombier calc = boolcopyfn(dst, mask);
6847dd7cddfSDavid du Colombier wrdst = nullwrite;
6857dd7cddfSDavid du Colombier }else{
6867dd7cddfSDavid du Colombier /* usual alphadraw parameter fetching */
6877dd7cddfSDavid du Colombier rdsrc = readfn(src);
6887dd7cddfSDavid du Colombier rddst = readfn(dst);
6897dd7cddfSDavid du Colombier wrdst = writefn(dst);
6906a9fc400SDavid du Colombier calc = alphacalc[op];
6917dd7cddfSDavid du Colombier
6927dd7cddfSDavid du Colombier /*
6937dd7cddfSDavid du Colombier * If there is no alpha channel, we'll ask for a grey channel
6947dd7cddfSDavid du Colombier * and pretend it is the alpha.
6957dd7cddfSDavid du Colombier */
6967dd7cddfSDavid du Colombier if(mask->flags&Falpha){
6977dd7cddfSDavid du Colombier rdmask = readalphafn(mask);
698*2c1878b4SDavid du Colombier z->mpar.alphaonly = 1;
6997dd7cddfSDavid du Colombier }else{
700*2c1878b4SDavid du Colombier z->mpar.greymaskcall = readfn(mask);
701*2c1878b4SDavid du Colombier z->mpar.convgrey = 1;
7027dd7cddfSDavid du Colombier rdmask = greymaskread;
7037dd7cddfSDavid du Colombier
7047dd7cddfSDavid du Colombier /*
7057dd7cddfSDavid du Colombier * Should really be above, but then boolcopyfns would have
7067dd7cddfSDavid du Colombier * to deal with bit alignment, and I haven't written that.
7077dd7cddfSDavid du Colombier *
7087dd7cddfSDavid du Colombier * This is a common case for things like ellipse drawing.
7097dd7cddfSDavid du Colombier * When there's no alpha involved and the mask is boolean,
7107dd7cddfSDavid du Colombier * we can avoid all the division and multiplication.
7117dd7cddfSDavid du Colombier */
7127dd7cddfSDavid du Colombier if(mask->chan == GREY1 && !(src->flags&Falpha))
7136a9fc400SDavid du Colombier calc = boolcalc[op];
7146a9fc400SDavid du Colombier else if(op == SoverD && !(src->flags&Falpha))
7156a9fc400SDavid du Colombier calc = alphacalcS;
7167dd7cddfSDavid du Colombier }
7177dd7cddfSDavid du Colombier }
7187dd7cddfSDavid du Colombier
7197dd7cddfSDavid du Colombier /*
7207dd7cddfSDavid du Colombier * If the image has a small enough repl rectangle,
7217dd7cddfSDavid du Colombier * we can just read each line once and cache them.
7227dd7cddfSDavid du Colombier */
723*2c1878b4SDavid du Colombier if(z->spar.replcache){
724*2c1878b4SDavid du Colombier z->spar.replcall = rdsrc;
7257dd7cddfSDavid du Colombier rdsrc = replread;
7267dd7cddfSDavid du Colombier }
727*2c1878b4SDavid du Colombier if(z->mpar.replcache){
728*2c1878b4SDavid du Colombier z->mpar.replcall = rdmask;
7297dd7cddfSDavid du Colombier rdmask = replread;
7307dd7cddfSDavid du Colombier }
7317dd7cddfSDavid du Colombier
732*2c1878b4SDavid du Colombier if(z->n < ndrawbuf){
733*2c1878b4SDavid du Colombier free(z->p);
734*2c1878b4SDavid du Colombier if((z->p = mallocz(ndrawbuf, 0)) == nil){
735*2c1878b4SDavid du Colombier z->inuse = 0;
7367dd7cddfSDavid du Colombier return 0;
737*2c1878b4SDavid du Colombier }
738*2c1878b4SDavid du Colombier z->n = ndrawbuf;
739*2c1878b4SDavid du Colombier }
740*2c1878b4SDavid du Colombier drawbuf = z->p;
7417dd7cddfSDavid du Colombier
7427dd7cddfSDavid du Colombier /*
7437dd7cddfSDavid du Colombier * Before we were saving only offsets from drawbuf in the parameter
7447dd7cddfSDavid du Colombier * structures; now that drawbuf has been grown to accomodate us,
7457dd7cddfSDavid du Colombier * we can fill in the pointers.
7467dd7cddfSDavid du Colombier */
747*2c1878b4SDavid du Colombier z->spar.bufbase = drawbuf+z->spar.bufoff;
748*2c1878b4SDavid du Colombier z->mpar.bufbase = drawbuf+z->mpar.bufoff;
749*2c1878b4SDavid du Colombier z->dpar.bufbase = drawbuf+z->dpar.bufoff;
750*2c1878b4SDavid du Colombier z->spar.convbuf = drawbuf+z->spar.convbufoff;
7517dd7cddfSDavid du Colombier
7527dd7cddfSDavid du Colombier if(dir == 1){
7537dd7cddfSDavid du Colombier starty = 0;
7547dd7cddfSDavid du Colombier endy = dy;
7557dd7cddfSDavid du Colombier }else{
7567dd7cddfSDavid du Colombier starty = dy-1;
7577dd7cddfSDavid du Colombier endy = -1;
7587dd7cddfSDavid du Colombier }
7597dd7cddfSDavid du Colombier
7607dd7cddfSDavid du Colombier /*
7617dd7cddfSDavid du Colombier * srcy, masky, and dsty are offsets from the top of their
7627dd7cddfSDavid du Colombier * respective Rectangles. they need to be contained within
7637dd7cddfSDavid du Colombier * the rectangles, so clipy can keep them there without division.
7647dd7cddfSDavid du Colombier */
7657dd7cddfSDavid du Colombier srcy = (starty + sr.min.y - src->r.min.y)%Dy(src->r);
7667dd7cddfSDavid du Colombier masky = (starty + mr.min.y - mask->r.min.y)%Dy(mask->r);
7677dd7cddfSDavid du Colombier dsty = starty + r.min.y - dst->r.min.y;
7687dd7cddfSDavid du Colombier
7697dd7cddfSDavid du Colombier assert(0 <= srcy && srcy < Dy(src->r));
7707dd7cddfSDavid du Colombier assert(0 <= masky && masky < Dy(mask->r));
7717dd7cddfSDavid du Colombier assert(0 <= dsty && dsty < Dy(dst->r));
7727dd7cddfSDavid du Colombier
7737dd7cddfSDavid du Colombier for(y=starty; y!=endy; y+=dir, srcy+=dir, masky+=dir, dsty+=dir){
7747dd7cddfSDavid du Colombier clipy(src, &srcy);
7757dd7cddfSDavid du Colombier clipy(dst, &dsty);
7767dd7cddfSDavid du Colombier clipy(mask, &masky);
7777dd7cddfSDavid du Colombier
778*2c1878b4SDavid du Colombier bsrc = rdsrc(&z->spar, z->spar.bufbase, srcy);
7797dd7cddfSDavid du Colombier DBG print("[");
780*2c1878b4SDavid du Colombier bmask = rdmask(&z->mpar, z->mpar.bufbase, masky);
7817dd7cddfSDavid du Colombier DBG print("]\n");
782*2c1878b4SDavid du Colombier bdst = rddst(&z->dpar, z->dpar.bufbase, dsty);
7837dd7cddfSDavid du Colombier DBG dumpbuf("src", bsrc, dx);
7847dd7cddfSDavid du Colombier DBG dumpbuf("mask", bmask, dx);
7857dd7cddfSDavid du Colombier DBG dumpbuf("dst", bdst, dx);
7866a9fc400SDavid du Colombier bdst = calc(bdst, bsrc, bmask, dx, isgrey, op);
787*2c1878b4SDavid du Colombier wrdst(&z->dpar, z->dpar.bytermin+dsty*z->dpar.bwidth, bdst);
7887dd7cddfSDavid du Colombier }
7897dd7cddfSDavid du Colombier
790*2c1878b4SDavid du Colombier z->inuse = 0;
7917dd7cddfSDavid du Colombier return 1;
7927dd7cddfSDavid du Colombier }
7937dd7cddfSDavid du Colombier #undef DBG
7947dd7cddfSDavid du Colombier
7957dd7cddfSDavid du Colombier static Buffer
alphacalc0(Buffer bdst,Buffer b1,Buffer b2,int dx,int grey,int op)7966a9fc400SDavid du Colombier alphacalc0(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op)
7976a9fc400SDavid du Colombier {
7986a9fc400SDavid du Colombier USED(grey);
7996a9fc400SDavid du Colombier USED(op);
8006a9fc400SDavid du Colombier USED(b1);
8016a9fc400SDavid du Colombier USED(b2);
8026a9fc400SDavid du Colombier memset(bdst.rgba, 0, dx*bdst.delta);
8036a9fc400SDavid du Colombier return bdst;
8046a9fc400SDavid du Colombier }
8056a9fc400SDavid du Colombier
8066a9fc400SDavid du Colombier static Buffer
alphacalc14(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)8076a9fc400SDavid du Colombier alphacalc14(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
8087dd7cddfSDavid du Colombier {
8097dd7cddfSDavid du Colombier Buffer obdst;
8106a9fc400SDavid du Colombier int fd, sadelta;
8116a9fc400SDavid du Colombier int i, sa, ma, q;
8126a9fc400SDavid du Colombier ulong s, t;
8137dd7cddfSDavid du Colombier
8147dd7cddfSDavid du Colombier obdst = bdst;
8156a9fc400SDavid du Colombier sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
8166a9fc400SDavid du Colombier q = bsrc.delta == 4 && bdst.delta == 4;
8177dd7cddfSDavid du Colombier
8187dd7cddfSDavid du Colombier for(i=0; i<dx; i++){
8196a9fc400SDavid du Colombier sa = *bsrc.alpha;
8207dd7cddfSDavid du Colombier ma = *bmask.alpha;
8216a9fc400SDavid du Colombier fd = MUL(sa, ma, t);
8226a9fc400SDavid du Colombier if(op == DoutS)
8236a9fc400SDavid du Colombier fd = 255-fd;
8247dd7cddfSDavid du Colombier
8257dd7cddfSDavid du Colombier if(grey){
8266a9fc400SDavid du Colombier *bdst.grey = MUL(fd, *bdst.grey, t);
8277dd7cddfSDavid du Colombier bsrc.grey += bsrc.delta;
8287dd7cddfSDavid du Colombier bdst.grey += bdst.delta;
8297dd7cddfSDavid du Colombier }else{
8306a9fc400SDavid du Colombier if(q){
8316a9fc400SDavid du Colombier *bdst.rgba = MUL0123(fd, *bdst.rgba, s, t);
8326a9fc400SDavid du Colombier bsrc.rgba++;
8336a9fc400SDavid du Colombier bdst.rgba++;
8346a9fc400SDavid du Colombier bsrc.alpha += sadelta;
8356a9fc400SDavid du Colombier bmask.alpha += bmask.delta;
8366a9fc400SDavid du Colombier continue;
8376a9fc400SDavid du Colombier }
8386a9fc400SDavid du Colombier *bdst.red = MUL(fd, *bdst.red, t);
8396a9fc400SDavid du Colombier *bdst.grn = MUL(fd, *bdst.grn, t);
8406a9fc400SDavid du Colombier *bdst.blu = MUL(fd, *bdst.blu, t);
8417dd7cddfSDavid du Colombier bsrc.red += bsrc.delta;
8427dd7cddfSDavid du Colombier bsrc.blu += bsrc.delta;
8437dd7cddfSDavid du Colombier bsrc.grn += bsrc.delta;
8447dd7cddfSDavid du Colombier bdst.red += bdst.delta;
8457dd7cddfSDavid du Colombier bdst.blu += bdst.delta;
8467dd7cddfSDavid du Colombier bdst.grn += bdst.delta;
8477dd7cddfSDavid du Colombier }
8486a9fc400SDavid du Colombier if(bdst.alpha != &ones){
8496a9fc400SDavid du Colombier *bdst.alpha = MUL(fd, *bdst.alpha, t);
8506a9fc400SDavid du Colombier bdst.alpha += bdst.delta;
8516a9fc400SDavid du Colombier }
8527dd7cddfSDavid du Colombier bmask.alpha += bmask.delta;
8536a9fc400SDavid du Colombier bsrc.alpha += sadelta;
8546a9fc400SDavid du Colombier }
8556a9fc400SDavid du Colombier return obdst;
8566a9fc400SDavid du Colombier }
8577dd7cddfSDavid du Colombier
8586a9fc400SDavid du Colombier static Buffer
alphacalc2810(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)8596a9fc400SDavid du Colombier alphacalc2810(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
8606a9fc400SDavid du Colombier {
8616a9fc400SDavid du Colombier Buffer obdst;
8626a9fc400SDavid du Colombier int fs, sadelta;
8636a9fc400SDavid du Colombier int i, ma, da, q;
8646a9fc400SDavid du Colombier ulong s, t;
8656a9fc400SDavid du Colombier
8666a9fc400SDavid du Colombier obdst = bdst;
8676a9fc400SDavid du Colombier sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
8686a9fc400SDavid du Colombier q = bsrc.delta == 4 && bdst.delta == 4;
8696a9fc400SDavid du Colombier
8706a9fc400SDavid du Colombier for(i=0; i<dx; i++){
8716a9fc400SDavid du Colombier ma = *bmask.alpha;
8726a9fc400SDavid du Colombier da = *bdst.alpha;
8736a9fc400SDavid du Colombier if(op == SoutD)
8746a9fc400SDavid du Colombier da = 255-da;
8756a9fc400SDavid du Colombier fs = ma;
8766a9fc400SDavid du Colombier if(op != S)
8776a9fc400SDavid du Colombier fs = MUL(fs, da, t);
8786a9fc400SDavid du Colombier
8796a9fc400SDavid du Colombier if(grey){
8806a9fc400SDavid du Colombier *bdst.grey = MUL(fs, *bsrc.grey, t);
8816a9fc400SDavid du Colombier bsrc.grey += bsrc.delta;
8826a9fc400SDavid du Colombier bdst.grey += bdst.delta;
8836a9fc400SDavid du Colombier }else{
8846a9fc400SDavid du Colombier if(q){
8856a9fc400SDavid du Colombier *bdst.rgba = MUL0123(fs, *bsrc.rgba, s, t);
8866a9fc400SDavid du Colombier bsrc.rgba++;
8876a9fc400SDavid du Colombier bdst.rgba++;
8886a9fc400SDavid du Colombier bmask.alpha += bmask.delta;
8896a9fc400SDavid du Colombier bdst.alpha += bdst.delta;
8906a9fc400SDavid du Colombier continue;
8916a9fc400SDavid du Colombier }
8926a9fc400SDavid du Colombier *bdst.red = MUL(fs, *bsrc.red, t);
8936a9fc400SDavid du Colombier *bdst.grn = MUL(fs, *bsrc.grn, t);
8946a9fc400SDavid du Colombier *bdst.blu = MUL(fs, *bsrc.blu, t);
8956a9fc400SDavid du Colombier bsrc.red += bsrc.delta;
8966a9fc400SDavid du Colombier bsrc.blu += bsrc.delta;
8976a9fc400SDavid du Colombier bsrc.grn += bsrc.delta;
8986a9fc400SDavid du Colombier bdst.red += bdst.delta;
8996a9fc400SDavid du Colombier bdst.blu += bdst.delta;
9006a9fc400SDavid du Colombier bdst.grn += bdst.delta;
9016a9fc400SDavid du Colombier }
9026a9fc400SDavid du Colombier if(bdst.alpha != &ones){
9036a9fc400SDavid du Colombier *bdst.alpha = MUL(fs, *bsrc.alpha, t);
9046a9fc400SDavid du Colombier bdst.alpha += bdst.delta;
9056a9fc400SDavid du Colombier }
9066a9fc400SDavid du Colombier bmask.alpha += bmask.delta;
9076a9fc400SDavid du Colombier bsrc.alpha += sadelta;
9086a9fc400SDavid du Colombier }
9096a9fc400SDavid du Colombier return obdst;
9106a9fc400SDavid du Colombier }
9116a9fc400SDavid du Colombier
9126a9fc400SDavid du Colombier static Buffer
alphacalc3679(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)9136a9fc400SDavid du Colombier alphacalc3679(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
9146a9fc400SDavid du Colombier {
9156a9fc400SDavid du Colombier Buffer obdst;
9166a9fc400SDavid du Colombier int fs, fd, sadelta;
9176a9fc400SDavid du Colombier int i, sa, ma, da, q;
9186a9fc400SDavid du Colombier ulong s, t, u, v;
9196a9fc400SDavid du Colombier
9206a9fc400SDavid du Colombier obdst = bdst;
9216a9fc400SDavid du Colombier sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
9226a9fc400SDavid du Colombier q = bsrc.delta == 4 && bdst.delta == 4;
9236a9fc400SDavid du Colombier
9246a9fc400SDavid du Colombier for(i=0; i<dx; i++){
9256a9fc400SDavid du Colombier sa = *bsrc.alpha;
9266a9fc400SDavid du Colombier ma = *bmask.alpha;
9276a9fc400SDavid du Colombier da = *bdst.alpha;
9286a9fc400SDavid du Colombier if(op == SatopD)
9296a9fc400SDavid du Colombier fs = MUL(ma, da, t);
9306a9fc400SDavid du Colombier else
9316a9fc400SDavid du Colombier fs = MUL(ma, 255-da, t);
9326a9fc400SDavid du Colombier if(op == DoverS)
9336a9fc400SDavid du Colombier fd = 255;
9346a9fc400SDavid du Colombier else{
9356a9fc400SDavid du Colombier fd = MUL(sa, ma, t);
9366a9fc400SDavid du Colombier if(op != DatopS)
9376a9fc400SDavid du Colombier fd = 255-fd;
9386a9fc400SDavid du Colombier }
9396a9fc400SDavid du Colombier
9406a9fc400SDavid du Colombier if(grey){
9416a9fc400SDavid du Colombier *bdst.grey = MUL(fs, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
9426a9fc400SDavid du Colombier bsrc.grey += bsrc.delta;
9436a9fc400SDavid du Colombier bdst.grey += bdst.delta;
9446a9fc400SDavid du Colombier }else{
9456a9fc400SDavid du Colombier if(q){
9466a9fc400SDavid du Colombier *bdst.rgba = MUL0123(fs, *bsrc.rgba, s, t)+MUL0123(fd, *bdst.rgba, u, v);
9476a9fc400SDavid du Colombier bsrc.rgba++;
9486a9fc400SDavid du Colombier bdst.rgba++;
9496a9fc400SDavid du Colombier bsrc.alpha += sadelta;
9506a9fc400SDavid du Colombier bmask.alpha += bmask.delta;
9516a9fc400SDavid du Colombier bdst.alpha += bdst.delta;
9526a9fc400SDavid du Colombier continue;
9536a9fc400SDavid du Colombier }
9546a9fc400SDavid du Colombier *bdst.red = MUL(fs, *bsrc.red, s)+MUL(fd, *bdst.red, t);
9556a9fc400SDavid du Colombier *bdst.grn = MUL(fs, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
9566a9fc400SDavid du Colombier *bdst.blu = MUL(fs, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
9576a9fc400SDavid du Colombier bsrc.red += bsrc.delta;
9586a9fc400SDavid du Colombier bsrc.blu += bsrc.delta;
9596a9fc400SDavid du Colombier bsrc.grn += bsrc.delta;
9606a9fc400SDavid du Colombier bdst.red += bdst.delta;
9616a9fc400SDavid du Colombier bdst.blu += bdst.delta;
9626a9fc400SDavid du Colombier bdst.grn += bdst.delta;
9636a9fc400SDavid du Colombier }
9646a9fc400SDavid du Colombier if(bdst.alpha != &ones){
9656a9fc400SDavid du Colombier *bdst.alpha = MUL(fs, sa, s)+MUL(fd, da, t);
9666a9fc400SDavid du Colombier bdst.alpha += bdst.delta;
9676a9fc400SDavid du Colombier }
9686a9fc400SDavid du Colombier bmask.alpha += bmask.delta;
9696a9fc400SDavid du Colombier bsrc.alpha += sadelta;
9706a9fc400SDavid du Colombier }
9716a9fc400SDavid du Colombier return obdst;
9726a9fc400SDavid du Colombier }
9736a9fc400SDavid du Colombier
9746a9fc400SDavid du Colombier static Buffer
alphacalc5(Buffer bdst,Buffer b1,Buffer b2,int dx,int grey,int op)9756a9fc400SDavid du Colombier alphacalc5(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op)
9766a9fc400SDavid du Colombier {
9776a9fc400SDavid du Colombier USED(dx);
9786a9fc400SDavid du Colombier USED(grey);
9796a9fc400SDavid du Colombier USED(op);
9806a9fc400SDavid du Colombier USED(b1);
9816a9fc400SDavid du Colombier USED(b2);
9826a9fc400SDavid du Colombier return bdst;
9836a9fc400SDavid du Colombier }
9846a9fc400SDavid du Colombier
9856a9fc400SDavid du Colombier static Buffer
alphacalc11(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)9866a9fc400SDavid du Colombier alphacalc11(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
9876a9fc400SDavid du Colombier {
9886a9fc400SDavid du Colombier Buffer obdst;
9896a9fc400SDavid du Colombier int fd, sadelta;
9906a9fc400SDavid du Colombier int i, sa, ma, q;
9916a9fc400SDavid du Colombier ulong s, t, u, v;
9926a9fc400SDavid du Colombier
9936a9fc400SDavid du Colombier USED(op);
9946a9fc400SDavid du Colombier obdst = bdst;
9956a9fc400SDavid du Colombier sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
9966a9fc400SDavid du Colombier q = bsrc.delta == 4 && bdst.delta == 4;
9976a9fc400SDavid du Colombier
9986a9fc400SDavid du Colombier for(i=0; i<dx; i++){
9996a9fc400SDavid du Colombier sa = *bsrc.alpha;
10006a9fc400SDavid du Colombier ma = *bmask.alpha;
10016a9fc400SDavid du Colombier fd = 255-MUL(sa, ma, t);
10026a9fc400SDavid du Colombier
10036a9fc400SDavid du Colombier if(grey){
10046a9fc400SDavid du Colombier *bdst.grey = MUL(ma, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
10056a9fc400SDavid du Colombier bsrc.grey += bsrc.delta;
10066a9fc400SDavid du Colombier bdst.grey += bdst.delta;
10076a9fc400SDavid du Colombier }else{
10086a9fc400SDavid du Colombier if(q){
10096a9fc400SDavid du Colombier *bdst.rgba = MUL0123(ma, *bsrc.rgba, s, t)+MUL0123(fd, *bdst.rgba, u, v);
10106a9fc400SDavid du Colombier bsrc.rgba++;
10116a9fc400SDavid du Colombier bdst.rgba++;
10126a9fc400SDavid du Colombier bsrc.alpha += sadelta;
10136a9fc400SDavid du Colombier bmask.alpha += bmask.delta;
10146a9fc400SDavid du Colombier continue;
10156a9fc400SDavid du Colombier }
10166a9fc400SDavid du Colombier *bdst.red = MUL(ma, *bsrc.red, s)+MUL(fd, *bdst.red, t);
10176a9fc400SDavid du Colombier *bdst.grn = MUL(ma, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
10186a9fc400SDavid du Colombier *bdst.blu = MUL(ma, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
10196a9fc400SDavid du Colombier bsrc.red += bsrc.delta;
10206a9fc400SDavid du Colombier bsrc.blu += bsrc.delta;
10216a9fc400SDavid du Colombier bsrc.grn += bsrc.delta;
10226a9fc400SDavid du Colombier bdst.red += bdst.delta;
10236a9fc400SDavid du Colombier bdst.blu += bdst.delta;
10246a9fc400SDavid du Colombier bdst.grn += bdst.delta;
10256a9fc400SDavid du Colombier }
10266a9fc400SDavid du Colombier if(bdst.alpha != &ones){
10276a9fc400SDavid du Colombier *bdst.alpha = MUL(ma, sa, s)+MUL(fd, *bdst.alpha, t);
10286a9fc400SDavid du Colombier bdst.alpha += bdst.delta;
10296a9fc400SDavid du Colombier }
10306a9fc400SDavid du Colombier bmask.alpha += bmask.delta;
10316a9fc400SDavid du Colombier bsrc.alpha += sadelta;
10326a9fc400SDavid du Colombier }
10336a9fc400SDavid du Colombier return obdst;
10346a9fc400SDavid du Colombier }
10356a9fc400SDavid du Colombier
10366a9fc400SDavid du Colombier /*
10376a9fc400SDavid du Colombier not used yet
10386a9fc400SDavid du Colombier source and mask alpha 1
10396a9fc400SDavid du Colombier static Buffer
10406a9fc400SDavid du Colombier alphacalcS0(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
10416a9fc400SDavid du Colombier {
10426a9fc400SDavid du Colombier Buffer obdst;
10436a9fc400SDavid du Colombier int i;
10446a9fc400SDavid du Colombier
10456a9fc400SDavid du Colombier USED(op);
10466a9fc400SDavid du Colombier obdst = bdst;
10476a9fc400SDavid du Colombier if(bsrc.delta == bdst.delta){
10486a9fc400SDavid du Colombier memmove(bdst.rgba, bsrc.rgba, dx*bdst.delta);
10496a9fc400SDavid du Colombier return obdst;
10506a9fc400SDavid du Colombier }
10516a9fc400SDavid du Colombier for(i=0; i<dx; i++){
10526a9fc400SDavid du Colombier if(grey){
10536a9fc400SDavid du Colombier *bdst.grey = *bsrc.grey;
10546a9fc400SDavid du Colombier bsrc.grey += bsrc.delta;
10556a9fc400SDavid du Colombier bdst.grey += bdst.delta;
10566a9fc400SDavid du Colombier }else{
10576a9fc400SDavid du Colombier *bdst.red = *bsrc.red;
10586a9fc400SDavid du Colombier *bdst.grn = *bsrc.grn;
10596a9fc400SDavid du Colombier *bdst.blu = *bsrc.blu;
10606a9fc400SDavid du Colombier bsrc.red += bsrc.delta;
10616a9fc400SDavid du Colombier bsrc.blu += bsrc.delta;
10626a9fc400SDavid du Colombier bsrc.grn += bsrc.delta;
10636a9fc400SDavid du Colombier bdst.red += bdst.delta;
10646a9fc400SDavid du Colombier bdst.blu += bdst.delta;
10656a9fc400SDavid du Colombier bdst.grn += bdst.delta;
10666a9fc400SDavid du Colombier }
10676a9fc400SDavid du Colombier if(bdst.alpha != &ones){
10686a9fc400SDavid du Colombier *bdst.alpha = 255;
10697dd7cddfSDavid du Colombier bdst.alpha += bdst.delta;
10707dd7cddfSDavid du Colombier }
10717dd7cddfSDavid du Colombier }
10727dd7cddfSDavid du Colombier return obdst;
10737dd7cddfSDavid du Colombier }
10746a9fc400SDavid du Colombier */
10757dd7cddfSDavid du Colombier
10766a9fc400SDavid du Colombier /* source alpha 1 */
10777dd7cddfSDavid du Colombier static Buffer
alphacalcS(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)10786a9fc400SDavid du Colombier alphacalcS(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
10797dd7cddfSDavid du Colombier {
10807dd7cddfSDavid du Colombier Buffer obdst;
10816a9fc400SDavid du Colombier int fd;
10827dd7cddfSDavid du Colombier int i, ma;
10836a9fc400SDavid du Colombier ulong s, t;
10847dd7cddfSDavid du Colombier
10856a9fc400SDavid du Colombier USED(op);
10867dd7cddfSDavid du Colombier obdst = bdst;
10876a9fc400SDavid du Colombier
10887dd7cddfSDavid du Colombier for(i=0; i<dx; i++){
10897dd7cddfSDavid du Colombier ma = *bmask.alpha;
10906a9fc400SDavid du Colombier fd = 255-ma;
10917dd7cddfSDavid du Colombier
10927dd7cddfSDavid du Colombier if(grey){
10936a9fc400SDavid du Colombier *bdst.grey = MUL(ma, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
10946a9fc400SDavid du Colombier bsrc.grey += bsrc.delta;
10956a9fc400SDavid du Colombier bdst.grey += bdst.delta;
10966a9fc400SDavid du Colombier }else{
10976a9fc400SDavid du Colombier *bdst.red = MUL(ma, *bsrc.red, s)+MUL(fd, *bdst.red, t);
10986a9fc400SDavid du Colombier *bdst.grn = MUL(ma, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
10996a9fc400SDavid du Colombier *bdst.blu = MUL(ma, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
11006a9fc400SDavid du Colombier bsrc.red += bsrc.delta;
11016a9fc400SDavid du Colombier bsrc.blu += bsrc.delta;
11026a9fc400SDavid du Colombier bsrc.grn += bsrc.delta;
11036a9fc400SDavid du Colombier bdst.red += bdst.delta;
11046a9fc400SDavid du Colombier bdst.blu += bdst.delta;
11056a9fc400SDavid du Colombier bdst.grn += bdst.delta;
11066a9fc400SDavid du Colombier }
11076a9fc400SDavid du Colombier if(bdst.alpha != &ones){
11086a9fc400SDavid du Colombier *bdst.alpha = ma+MUL(fd, *bdst.alpha, t);
11096a9fc400SDavid du Colombier bdst.alpha += bdst.delta;
11106a9fc400SDavid du Colombier }
11116a9fc400SDavid du Colombier bmask.alpha += bmask.delta;
11126a9fc400SDavid du Colombier }
11136a9fc400SDavid du Colombier return obdst;
11146a9fc400SDavid du Colombier }
11156a9fc400SDavid du Colombier
11166a9fc400SDavid du Colombier static Buffer
boolcalc14(Buffer bdst,Buffer b1,Buffer bmask,int dx,int grey,int op)11176a9fc400SDavid du Colombier boolcalc14(Buffer bdst, Buffer b1, Buffer bmask, int dx, int grey, int op)
11186a9fc400SDavid du Colombier {
11196a9fc400SDavid du Colombier Buffer obdst;
11206a9fc400SDavid du Colombier int i, ma, zero;
11216a9fc400SDavid du Colombier
11226a9fc400SDavid du Colombier USED(b1);
11236a9fc400SDavid du Colombier
11246a9fc400SDavid du Colombier obdst = bdst;
11256a9fc400SDavid du Colombier
11266a9fc400SDavid du Colombier for(i=0; i<dx; i++){
11276a9fc400SDavid du Colombier ma = *bmask.alpha;
11286a9fc400SDavid du Colombier zero = ma ? op == DoutS : op == DinS;
11296a9fc400SDavid du Colombier
11306a9fc400SDavid du Colombier if(grey){
11316a9fc400SDavid du Colombier if(zero)
11326a9fc400SDavid du Colombier *bdst.grey = 0;
11336a9fc400SDavid du Colombier bdst.grey += bdst.delta;
11346a9fc400SDavid du Colombier }else{
11356a9fc400SDavid du Colombier if(zero)
11366a9fc400SDavid du Colombier *bdst.red = *bdst.grn = *bdst.blu = 0;
11376a9fc400SDavid du Colombier bdst.red += bdst.delta;
11386a9fc400SDavid du Colombier bdst.blu += bdst.delta;
11396a9fc400SDavid du Colombier bdst.grn += bdst.delta;
11406a9fc400SDavid du Colombier }
11416a9fc400SDavid du Colombier bmask.alpha += bmask.delta;
11426a9fc400SDavid du Colombier if(bdst.alpha != &ones){
11436a9fc400SDavid du Colombier if(zero)
11446a9fc400SDavid du Colombier *bdst.alpha = 0;
11456a9fc400SDavid du Colombier bdst.alpha += bdst.delta;
11466a9fc400SDavid du Colombier }
11476a9fc400SDavid du Colombier }
11486a9fc400SDavid du Colombier return obdst;
11496a9fc400SDavid du Colombier }
11506a9fc400SDavid du Colombier
11516a9fc400SDavid du Colombier static Buffer
boolcalc236789(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)11526a9fc400SDavid du Colombier boolcalc236789(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
11536a9fc400SDavid du Colombier {
11546a9fc400SDavid du Colombier Buffer obdst;
11556a9fc400SDavid du Colombier int fs, fd;
11566a9fc400SDavid du Colombier int i, ma, da, zero;
11576a9fc400SDavid du Colombier ulong s, t;
11586a9fc400SDavid du Colombier
11596a9fc400SDavid du Colombier obdst = bdst;
11606a9fc400SDavid du Colombier zero = !(op&1);
11616a9fc400SDavid du Colombier
11626a9fc400SDavid du Colombier for(i=0; i<dx; i++){
11636a9fc400SDavid du Colombier ma = *bmask.alpha;
11646a9fc400SDavid du Colombier da = *bdst.alpha;
11656a9fc400SDavid du Colombier fs = da;
11666a9fc400SDavid du Colombier if(op&2)
11676a9fc400SDavid du Colombier fs = 255-da;
11686a9fc400SDavid du Colombier fd = 0;
11696a9fc400SDavid du Colombier if(op&4)
11706a9fc400SDavid du Colombier fd = 255;
11716a9fc400SDavid du Colombier
11726a9fc400SDavid du Colombier if(grey){
11737dd7cddfSDavid du Colombier if(ma)
11746a9fc400SDavid du Colombier *bdst.grey = MUL(fs, *bsrc.grey, s)+MUL(fd, *bdst.grey, t);
11756a9fc400SDavid du Colombier else if(zero)
11766a9fc400SDavid du Colombier *bdst.grey = 0;
11777dd7cddfSDavid du Colombier bsrc.grey += bsrc.delta;
11787dd7cddfSDavid du Colombier bdst.grey += bdst.delta;
11797dd7cddfSDavid du Colombier }else{
11807dd7cddfSDavid du Colombier if(ma){
11816a9fc400SDavid du Colombier *bdst.red = MUL(fs, *bsrc.red, s)+MUL(fd, *bdst.red, t);
11826a9fc400SDavid du Colombier *bdst.grn = MUL(fs, *bsrc.grn, s)+MUL(fd, *bdst.grn, t);
11836a9fc400SDavid du Colombier *bdst.blu = MUL(fs, *bsrc.blu, s)+MUL(fd, *bdst.blu, t);
11847dd7cddfSDavid du Colombier }
11856a9fc400SDavid du Colombier else if(zero)
11866a9fc400SDavid du Colombier *bdst.red = *bdst.grn = *bdst.blu = 0;
11877dd7cddfSDavid du Colombier bsrc.red += bsrc.delta;
11887dd7cddfSDavid du Colombier bsrc.blu += bsrc.delta;
11897dd7cddfSDavid du Colombier bsrc.grn += bsrc.delta;
11907dd7cddfSDavid du Colombier bdst.red += bdst.delta;
11917dd7cddfSDavid du Colombier bdst.blu += bdst.delta;
11927dd7cddfSDavid du Colombier bdst.grn += bdst.delta;
11937dd7cddfSDavid du Colombier }
11947dd7cddfSDavid du Colombier bmask.alpha += bmask.delta;
11956a9fc400SDavid du Colombier if(bdst.alpha != &ones){
11967dd7cddfSDavid du Colombier if(ma)
11976a9fc400SDavid du Colombier *bdst.alpha = fs+MUL(fd, da, t);
11986a9fc400SDavid du Colombier else if(zero)
11996a9fc400SDavid du Colombier *bdst.alpha = 0;
12007dd7cddfSDavid du Colombier bdst.alpha += bdst.delta;
12017dd7cddfSDavid du Colombier }
12027dd7cddfSDavid du Colombier }
12037dd7cddfSDavid du Colombier return obdst;
12047dd7cddfSDavid du Colombier }
12057dd7cddfSDavid du Colombier
12066a9fc400SDavid du Colombier static Buffer
boolcalc1011(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)12076a9fc400SDavid du Colombier boolcalc1011(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
12086a9fc400SDavid du Colombier {
12096a9fc400SDavid du Colombier Buffer obdst;
12106a9fc400SDavid du Colombier int i, ma, zero;
12116a9fc400SDavid du Colombier
12126a9fc400SDavid du Colombier obdst = bdst;
12136a9fc400SDavid du Colombier zero = !(op&1);
12146a9fc400SDavid du Colombier
12156a9fc400SDavid du Colombier for(i=0; i<dx; i++){
12166a9fc400SDavid du Colombier ma = *bmask.alpha;
12176a9fc400SDavid du Colombier
12186a9fc400SDavid du Colombier if(grey){
12196a9fc400SDavid du Colombier if(ma)
12206a9fc400SDavid du Colombier *bdst.grey = *bsrc.grey;
12216a9fc400SDavid du Colombier else if(zero)
12226a9fc400SDavid du Colombier *bdst.grey = 0;
12236a9fc400SDavid du Colombier bsrc.grey += bsrc.delta;
12246a9fc400SDavid du Colombier bdst.grey += bdst.delta;
12256a9fc400SDavid du Colombier }else{
12266a9fc400SDavid du Colombier if(ma){
12276a9fc400SDavid du Colombier *bdst.red = *bsrc.red;
12286a9fc400SDavid du Colombier *bdst.grn = *bsrc.grn;
12296a9fc400SDavid du Colombier *bdst.blu = *bsrc.blu;
12306a9fc400SDavid du Colombier }
12316a9fc400SDavid du Colombier else if(zero)
12326a9fc400SDavid du Colombier *bdst.red = *bdst.grn = *bdst.blu = 0;
12336a9fc400SDavid du Colombier bsrc.red += bsrc.delta;
12346a9fc400SDavid du Colombier bsrc.blu += bsrc.delta;
12356a9fc400SDavid du Colombier bsrc.grn += bsrc.delta;
12366a9fc400SDavid du Colombier bdst.red += bdst.delta;
12376a9fc400SDavid du Colombier bdst.blu += bdst.delta;
12386a9fc400SDavid du Colombier bdst.grn += bdst.delta;
12396a9fc400SDavid du Colombier }
12406a9fc400SDavid du Colombier bmask.alpha += bmask.delta;
12416a9fc400SDavid du Colombier if(bdst.alpha != &ones){
12426a9fc400SDavid du Colombier if(ma)
12436a9fc400SDavid du Colombier *bdst.alpha = 255;
12446a9fc400SDavid du Colombier else if(zero)
12456a9fc400SDavid du Colombier *bdst.alpha = 0;
12466a9fc400SDavid du Colombier bdst.alpha += bdst.delta;
12476a9fc400SDavid du Colombier }
12486a9fc400SDavid du Colombier }
12496a9fc400SDavid du Colombier return obdst;
12506a9fc400SDavid du Colombier }
12517dd7cddfSDavid du Colombier /*
12527dd7cddfSDavid du Colombier * Replicated cached scan line read. Call the function listed in the Param,
12537dd7cddfSDavid du Colombier * but cache the result so that for replicated images we only do the work once.
12547dd7cddfSDavid du Colombier */
12557dd7cddfSDavid du Colombier static Buffer
replread(Param * p,uchar * s,int y)12566a9fc400SDavid du Colombier replread(Param *p, uchar *s, int y)
12577dd7cddfSDavid du Colombier {
12587dd7cddfSDavid du Colombier Buffer *b;
12597dd7cddfSDavid du Colombier
12606a9fc400SDavid du Colombier USED(s);
12617dd7cddfSDavid du Colombier b = &p->bcache[y];
12627dd7cddfSDavid du Colombier if((p->bfilled & (1<<y)) == 0){
12637dd7cddfSDavid du Colombier p->bfilled |= 1<<y;
12647dd7cddfSDavid du Colombier *b = p->replcall(p, p->bufbase+y*p->bufdelta, y);
12657dd7cddfSDavid du Colombier }
12667dd7cddfSDavid du Colombier return *b;
12677dd7cddfSDavid du Colombier }
12687dd7cddfSDavid du Colombier
12697dd7cddfSDavid du Colombier /*
12707dd7cddfSDavid du Colombier * Alpha reading function that simply relabels the grey pointer.
12717dd7cddfSDavid du Colombier */
12727dd7cddfSDavid du Colombier static Buffer
greymaskread(Param * p,uchar * buf,int y)12737dd7cddfSDavid du Colombier greymaskread(Param *p, uchar *buf, int y)
12747dd7cddfSDavid du Colombier {
12757dd7cddfSDavid du Colombier Buffer b;
12767dd7cddfSDavid du Colombier
12777dd7cddfSDavid du Colombier b = p->greymaskcall(p, buf, y);
12787dd7cddfSDavid du Colombier b.alpha = b.grey;
12797dd7cddfSDavid du Colombier return b;
12807dd7cddfSDavid du Colombier }
12817dd7cddfSDavid du Colombier
12827dd7cddfSDavid du Colombier #define DBG if(0)
12837dd7cddfSDavid du Colombier static Buffer
readnbit(Param * p,uchar * buf,int y)12847dd7cddfSDavid du Colombier readnbit(Param *p, uchar *buf, int y)
12857dd7cddfSDavid du Colombier {
12867dd7cddfSDavid du Colombier Buffer b;
12877dd7cddfSDavid du Colombier Memimage *img;
12887dd7cddfSDavid du Colombier uchar *repl, *r, *w, *ow, bits;
12897dd7cddfSDavid du Colombier int i, n, sh, depth, x, dx, npack, nbits;
12907dd7cddfSDavid du Colombier
12916a9fc400SDavid du Colombier b.rgba = (ulong*)buf;
12927dd7cddfSDavid du Colombier b.grey = w = buf;
12937dd7cddfSDavid du Colombier b.red = b.blu = b.grn = w;
12946a9fc400SDavid du Colombier b.alpha = &ones;
12957dd7cddfSDavid du Colombier b.delta = 1;
12967dd7cddfSDavid du Colombier
12977dd7cddfSDavid du Colombier dx = p->dx;
12987dd7cddfSDavid du Colombier img = p->img;
12997dd7cddfSDavid du Colombier depth = img->depth;
13007dd7cddfSDavid du Colombier repl = &replbit[depth][0];
13017dd7cddfSDavid du Colombier npack = 8/depth;
13027dd7cddfSDavid du Colombier sh = 8-depth;
13037dd7cddfSDavid du Colombier
13047dd7cddfSDavid du Colombier /* copy from p->r.min.x until end of repl rectangle */
13057dd7cddfSDavid du Colombier x = p->r.min.x;
13067dd7cddfSDavid du Colombier n = dx;
13077dd7cddfSDavid du Colombier if(n > p->img->r.max.x - x)
13087dd7cddfSDavid du Colombier n = p->img->r.max.x - x;
13097dd7cddfSDavid du Colombier
13107dd7cddfSDavid du Colombier r = p->bytermin + y*p->bwidth;
13117dd7cddfSDavid du Colombier DBG print("readnbit dx %d %p=%p+%d*%d, *r=%d fetch %d ", dx, r, p->bytermin, y, p->bwidth, *r, n);
13127dd7cddfSDavid du Colombier bits = *r++;
13137dd7cddfSDavid du Colombier nbits = 8;
13147dd7cddfSDavid du Colombier if(i=x&(npack-1)){
13157dd7cddfSDavid du Colombier DBG print("throwaway %d...", i);
13167dd7cddfSDavid du Colombier bits <<= depth*i;
13177dd7cddfSDavid du Colombier nbits -= depth*i;
13187dd7cddfSDavid du Colombier }
13197dd7cddfSDavid du Colombier for(i=0; i<n; i++){
13207dd7cddfSDavid du Colombier if(nbits == 0){
13217dd7cddfSDavid du Colombier DBG print("(%.2ux)...", *r);
13227dd7cddfSDavid du Colombier bits = *r++;
13237dd7cddfSDavid du Colombier nbits = 8;
13247dd7cddfSDavid du Colombier }
13257dd7cddfSDavid du Colombier *w++ = repl[bits>>sh];
13267dd7cddfSDavid du Colombier DBG print("bit %x...", repl[bits>>sh]);
13277dd7cddfSDavid du Colombier bits <<= depth;
13287dd7cddfSDavid du Colombier nbits -= depth;
13297dd7cddfSDavid du Colombier }
13307dd7cddfSDavid du Colombier dx -= n;
13317dd7cddfSDavid du Colombier if(dx == 0)
13327dd7cddfSDavid du Colombier return b;
13337dd7cddfSDavid du Colombier
13347dd7cddfSDavid du Colombier assert(x+i == p->img->r.max.x);
13357dd7cddfSDavid du Colombier
13367dd7cddfSDavid du Colombier /* copy from beginning of repl rectangle until where we were before. */
13377dd7cddfSDavid du Colombier x = p->img->r.min.x;
13387dd7cddfSDavid du Colombier n = dx;
13397dd7cddfSDavid du Colombier if(n > p->r.min.x - x)
13407dd7cddfSDavid du Colombier n = p->r.min.x - x;
13417dd7cddfSDavid du Colombier
13427dd7cddfSDavid du Colombier r = p->bytey0s + y*p->bwidth;
13437dd7cddfSDavid du Colombier DBG print("x=%d r=%p...", x, r);
13447dd7cddfSDavid du Colombier bits = *r++;
13457dd7cddfSDavid du Colombier nbits = 8;
13467dd7cddfSDavid du Colombier if(i=x&(npack-1)){
13477dd7cddfSDavid du Colombier bits <<= depth*i;
13487dd7cddfSDavid du Colombier nbits -= depth*i;
13497dd7cddfSDavid du Colombier }
13507dd7cddfSDavid du Colombier DBG print("nbits=%d...", nbits);
13517dd7cddfSDavid du Colombier for(i=0; i<n; i++){
13527dd7cddfSDavid du Colombier if(nbits == 0){
13537dd7cddfSDavid du Colombier bits = *r++;
13547dd7cddfSDavid du Colombier nbits = 8;
13557dd7cddfSDavid du Colombier }
13567dd7cddfSDavid du Colombier *w++ = repl[bits>>sh];
13577dd7cddfSDavid du Colombier DBG print("bit %x...", repl[bits>>sh]);
13587dd7cddfSDavid du Colombier bits <<= depth;
13597dd7cddfSDavid du Colombier nbits -= depth;
13607dd7cddfSDavid du Colombier DBG print("bits %x nbits %d...", bits, nbits);
13617dd7cddfSDavid du Colombier }
13627dd7cddfSDavid du Colombier dx -= n;
13637dd7cddfSDavid du Colombier if(dx == 0)
13647dd7cddfSDavid du Colombier return b;
13657dd7cddfSDavid du Colombier
13667dd7cddfSDavid du Colombier assert(dx > 0);
13677dd7cddfSDavid du Colombier /* now we have exactly one full scan line: just replicate the buffer itself until we are done */
13687dd7cddfSDavid du Colombier ow = buf;
13697dd7cddfSDavid du Colombier while(dx--)
13707dd7cddfSDavid du Colombier *w++ = *ow++;
13717dd7cddfSDavid du Colombier
13727dd7cddfSDavid du Colombier return b;
13737dd7cddfSDavid du Colombier }
13747dd7cddfSDavid du Colombier #undef DBG
13757dd7cddfSDavid du Colombier
13767dd7cddfSDavid du Colombier #define DBG if(0)
13777dd7cddfSDavid du Colombier static void
writenbit(Param * p,uchar * w,Buffer src)13787dd7cddfSDavid du Colombier writenbit(Param *p, uchar *w, Buffer src)
13797dd7cddfSDavid du Colombier {
13807dd7cddfSDavid du Colombier uchar *r;
13817dd7cddfSDavid du Colombier ulong bits;
13827dd7cddfSDavid du Colombier int i, sh, depth, npack, nbits, x, ex;
13837dd7cddfSDavid du Colombier
13847dd7cddfSDavid du Colombier assert(src.grey != nil && src.delta == 1);
13857dd7cddfSDavid du Colombier
13867dd7cddfSDavid du Colombier x = p->r.min.x;
13877dd7cddfSDavid du Colombier ex = x+p->dx;
13887dd7cddfSDavid du Colombier depth = p->img->depth;
13897dd7cddfSDavid du Colombier npack = 8/depth;
13907dd7cddfSDavid du Colombier
13917dd7cddfSDavid du Colombier i=x&(npack-1);
13927dd7cddfSDavid du Colombier bits = i ? (*w >> (8-depth*i)) : 0;
13937dd7cddfSDavid du Colombier nbits = depth*i;
13947dd7cddfSDavid du Colombier sh = 8-depth;
13957dd7cddfSDavid du Colombier r = src.grey;
13967dd7cddfSDavid du Colombier
13977dd7cddfSDavid du Colombier for(; x<ex; x++){
13987dd7cddfSDavid du Colombier bits <<= depth;
13997dd7cddfSDavid du Colombier DBG print(" %x", *r);
14007dd7cddfSDavid du Colombier bits |= (*r++ >> sh);
14017dd7cddfSDavid du Colombier nbits += depth;
14027dd7cddfSDavid du Colombier if(nbits == 8){
14037dd7cddfSDavid du Colombier *w++ = bits;
14047dd7cddfSDavid du Colombier nbits = 0;
14057dd7cddfSDavid du Colombier }
14067dd7cddfSDavid du Colombier }
14077dd7cddfSDavid du Colombier
14087dd7cddfSDavid du Colombier if(nbits){
14097dd7cddfSDavid du Colombier sh = 8-nbits;
14107dd7cddfSDavid du Colombier bits <<= sh;
14117dd7cddfSDavid du Colombier bits |= *w & ((1<<sh)-1);
14127dd7cddfSDavid du Colombier *w = bits;
14137dd7cddfSDavid du Colombier }
14147dd7cddfSDavid du Colombier DBG print("\n");
14157dd7cddfSDavid du Colombier return;
14167dd7cddfSDavid du Colombier }
14177dd7cddfSDavid du Colombier #undef DBG
14187dd7cddfSDavid du Colombier
14197dd7cddfSDavid du Colombier static Buffer
readcmap(Param * p,uchar * buf,int y)14207dd7cddfSDavid du Colombier readcmap(Param *p, uchar *buf, int y)
14217dd7cddfSDavid du Colombier {
14227dd7cddfSDavid du Colombier Buffer b;
142380ee5cbfSDavid du Colombier int a, convgrey, copyalpha, dx, i, m;
14247dd7cddfSDavid du Colombier uchar *q, *cmap, *begin, *end, *r, *w;
14257dd7cddfSDavid du Colombier
14267dd7cddfSDavid du Colombier begin = p->bytey0s + y*p->bwidth;
14277dd7cddfSDavid du Colombier r = p->bytermin + y*p->bwidth;
14287dd7cddfSDavid du Colombier end = p->bytey0e + y*p->bwidth;
14297dd7cddfSDavid du Colombier cmap = p->img->cmap->cmap2rgb;
14307dd7cddfSDavid du Colombier convgrey = p->convgrey;
143180ee5cbfSDavid du Colombier copyalpha = (p->img->flags&Falpha) ? 1 : 0;
14327dd7cddfSDavid du Colombier
14337dd7cddfSDavid du Colombier w = buf;
14347dd7cddfSDavid du Colombier dx = p->dx;
143580ee5cbfSDavid du Colombier if(copyalpha){
143680ee5cbfSDavid du Colombier b.alpha = buf++;
143780ee5cbfSDavid du Colombier a = p->img->shift[CAlpha]/8;
143880ee5cbfSDavid du Colombier m = p->img->shift[CMap]/8;
143980ee5cbfSDavid du Colombier for(i=0; i<dx; i++){
144080ee5cbfSDavid du Colombier *w++ = r[a];
144180ee5cbfSDavid du Colombier q = cmap+r[m]*3;
144280ee5cbfSDavid du Colombier r += 2;
144380ee5cbfSDavid du Colombier if(r == end)
144480ee5cbfSDavid du Colombier r = begin;
144580ee5cbfSDavid du Colombier if(convgrey){
144680ee5cbfSDavid du Colombier *w++ = RGB2K(q[0], q[1], q[2]);
144780ee5cbfSDavid du Colombier }else{
144880ee5cbfSDavid du Colombier *w++ = q[2]; /* blue */
144980ee5cbfSDavid du Colombier *w++ = q[1]; /* green */
145080ee5cbfSDavid du Colombier *w++ = q[0]; /* red */
145180ee5cbfSDavid du Colombier }
145280ee5cbfSDavid du Colombier }
145380ee5cbfSDavid du Colombier }else{
14546a9fc400SDavid du Colombier b.alpha = &ones;
14557dd7cddfSDavid du Colombier for(i=0; i<dx; i++){
14567dd7cddfSDavid du Colombier q = cmap+*r++*3;
14577dd7cddfSDavid du Colombier if(r == end)
14587dd7cddfSDavid du Colombier r = begin;
14597dd7cddfSDavid du Colombier if(convgrey){
14607dd7cddfSDavid du Colombier *w++ = RGB2K(q[0], q[1], q[2]);
14617dd7cddfSDavid du Colombier }else{
14627dd7cddfSDavid du Colombier *w++ = q[2]; /* blue */
14637dd7cddfSDavid du Colombier *w++ = q[1]; /* green */
14647dd7cddfSDavid du Colombier *w++ = q[0]; /* red */
14657dd7cddfSDavid du Colombier }
14667dd7cddfSDavid du Colombier }
146780ee5cbfSDavid du Colombier }
14687dd7cddfSDavid du Colombier
14696a9fc400SDavid du Colombier b.rgba = (ulong*)(buf-copyalpha);
14706a9fc400SDavid du Colombier
14717dd7cddfSDavid du Colombier if(convgrey){
14727dd7cddfSDavid du Colombier b.grey = buf;
14737dd7cddfSDavid du Colombier b.red = b.blu = b.grn = buf;
147480ee5cbfSDavid du Colombier b.delta = 1+copyalpha;
14757dd7cddfSDavid du Colombier }else{
14767dd7cddfSDavid du Colombier b.blu = buf;
14777dd7cddfSDavid du Colombier b.grn = buf+1;
14787dd7cddfSDavid du Colombier b.red = buf+2;
14797dd7cddfSDavid du Colombier b.grey = nil;
148080ee5cbfSDavid du Colombier b.delta = 3+copyalpha;
14817dd7cddfSDavid du Colombier }
14827dd7cddfSDavid du Colombier return b;
14837dd7cddfSDavid du Colombier }
14847dd7cddfSDavid du Colombier
14857dd7cddfSDavid du Colombier static void
writecmap(Param * p,uchar * w,Buffer src)14867dd7cddfSDavid du Colombier writecmap(Param *p, uchar *w, Buffer src)
14877dd7cddfSDavid du Colombier {
14887dd7cddfSDavid du Colombier uchar *cmap, *red, *grn, *blu;
14897dd7cddfSDavid du Colombier int i, dx, delta;
14907dd7cddfSDavid du Colombier
14917dd7cddfSDavid du Colombier cmap = p->img->cmap->rgb2cmap;
14927dd7cddfSDavid du Colombier
14937dd7cddfSDavid du Colombier delta = src.delta;
14947dd7cddfSDavid du Colombier red= src.red;
14957dd7cddfSDavid du Colombier grn = src.grn;
14967dd7cddfSDavid du Colombier blu = src.blu;
14977dd7cddfSDavid du Colombier
14987dd7cddfSDavid du Colombier dx = p->dx;
14997dd7cddfSDavid du Colombier for(i=0; i<dx; i++, red+=delta, grn+=delta, blu+=delta)
15007dd7cddfSDavid du Colombier *w++ = cmap[(*red>>4)*256+(*grn>>4)*16+(*blu>>4)];
15017dd7cddfSDavid du Colombier }
15027dd7cddfSDavid du Colombier
150359cc4ca5SDavid du Colombier #define DBG if(0)
15047dd7cddfSDavid du Colombier static Buffer
readbyte(Param * p,uchar * buf,int y)15057dd7cddfSDavid du Colombier readbyte(Param *p, uchar *buf, int y)
15067dd7cddfSDavid du Colombier {
15077dd7cddfSDavid du Colombier Buffer b;
15087dd7cddfSDavid du Colombier Memimage *img;
15097dd7cddfSDavid du Colombier int dx, isgrey, convgrey, alphaonly, copyalpha, i, nb;
15107dd7cddfSDavid du Colombier uchar *begin, *end, *r, *w, *rrepl, *grepl, *brepl, *arepl, *krepl;
15117dd7cddfSDavid du Colombier uchar ured, ugrn, ublu;
15127dd7cddfSDavid du Colombier ulong u;
15137dd7cddfSDavid du Colombier
15147dd7cddfSDavid du Colombier img = p->img;
15157dd7cddfSDavid du Colombier begin = p->bytey0s + y*p->bwidth;
15167dd7cddfSDavid du Colombier r = p->bytermin + y*p->bwidth;
15177dd7cddfSDavid du Colombier end = p->bytey0e + y*p->bwidth;
15187dd7cddfSDavid du Colombier
15197dd7cddfSDavid du Colombier w = buf;
15207dd7cddfSDavid du Colombier dx = p->dx;
15217dd7cddfSDavid du Colombier nb = img->depth/8;
15227dd7cddfSDavid du Colombier
15237dd7cddfSDavid du Colombier convgrey = p->convgrey; /* convert rgb to grey */
15247dd7cddfSDavid du Colombier isgrey = img->flags&Fgrey;
15257dd7cddfSDavid du Colombier alphaonly = p->alphaonly;
152659cc4ca5SDavid du Colombier copyalpha = (img->flags&Falpha) ? 1 : 0;
15277dd7cddfSDavid du Colombier
152859cc4ca5SDavid du Colombier DBG print("copyalpha %d alphaonly %d convgrey %d isgrey %d\n", copyalpha, alphaonly, convgrey, isgrey);
15297dd7cddfSDavid du Colombier /* if we can, avoid processing everything */
15307dd7cddfSDavid du Colombier if(!(img->flags&Frepl) && !convgrey && (img->flags&Fbytes)){
15317dd7cddfSDavid du Colombier memset(&b, 0, sizeof b);
15327dd7cddfSDavid du Colombier if(p->needbuf){
15337dd7cddfSDavid du Colombier memmove(buf, r, dx*nb);
15347dd7cddfSDavid du Colombier r = buf;
15357dd7cddfSDavid du Colombier }
15366a9fc400SDavid du Colombier b.rgba = (ulong*)r;
15377dd7cddfSDavid du Colombier if(copyalpha)
15387dd7cddfSDavid du Colombier b.alpha = r+img->shift[CAlpha]/8;
15396a9fc400SDavid du Colombier else
15406a9fc400SDavid du Colombier b.alpha = &ones;
15417dd7cddfSDavid du Colombier if(isgrey){
15427dd7cddfSDavid du Colombier b.grey = r+img->shift[CGrey]/8;
15437dd7cddfSDavid du Colombier b.red = b.grn = b.blu = b.grey;
15447dd7cddfSDavid du Colombier }else{
15457dd7cddfSDavid du Colombier b.red = r+img->shift[CRed]/8;
15467dd7cddfSDavid du Colombier b.grn = r+img->shift[CGreen]/8;
15477dd7cddfSDavid du Colombier b.blu = r+img->shift[CBlue]/8;
15487dd7cddfSDavid du Colombier }
15497dd7cddfSDavid du Colombier b.delta = nb;
15507dd7cddfSDavid du Colombier return b;
15517dd7cddfSDavid du Colombier }
15527dd7cddfSDavid du Colombier
155359cc4ca5SDavid du Colombier DBG print("2\n");
15547dd7cddfSDavid du Colombier rrepl = replbit[img->nbits[CRed]];
15557dd7cddfSDavid du Colombier grepl = replbit[img->nbits[CGreen]];
15567dd7cddfSDavid du Colombier brepl = replbit[img->nbits[CBlue]];
15577dd7cddfSDavid du Colombier arepl = replbit[img->nbits[CAlpha]];
15587dd7cddfSDavid du Colombier krepl = replbit[img->nbits[CGrey]];
15597dd7cddfSDavid du Colombier
15607dd7cddfSDavid du Colombier for(i=0; i<dx; i++){
15617dd7cddfSDavid du Colombier u = r[0] | (r[1]<<8) | (r[2]<<16) | (r[3]<<24);
156259cc4ca5SDavid du Colombier if(copyalpha) {
15637dd7cddfSDavid du Colombier *w++ = arepl[(u>>img->shift[CAlpha]) & img->mask[CAlpha]];
156459cc4ca5SDavid du Colombier DBG print("a %x\n", w[-1]);
156559cc4ca5SDavid du Colombier }
15667dd7cddfSDavid du Colombier
15677dd7cddfSDavid du Colombier if(isgrey)
15687dd7cddfSDavid du Colombier *w++ = krepl[(u >> img->shift[CGrey]) & img->mask[CGrey]];
15697dd7cddfSDavid du Colombier else if(!alphaonly){
15707dd7cddfSDavid du Colombier ured = rrepl[(u >> img->shift[CRed]) & img->mask[CRed]];
15717dd7cddfSDavid du Colombier ugrn = grepl[(u >> img->shift[CGreen]) & img->mask[CGreen]];
15727dd7cddfSDavid du Colombier ublu = brepl[(u >> img->shift[CBlue]) & img->mask[CBlue]];
15737dd7cddfSDavid du Colombier if(convgrey){
157459cc4ca5SDavid du Colombier DBG print("g %x %x %x\n", ured, ugrn, ublu);
15757dd7cddfSDavid du Colombier *w++ = RGB2K(ured, ugrn, ublu);
157659cc4ca5SDavid du Colombier DBG print("%x\n", w[-1]);
15777dd7cddfSDavid du Colombier }else{
15787dd7cddfSDavid du Colombier *w++ = brepl[(u >> img->shift[CBlue]) & img->mask[CBlue]];
15797dd7cddfSDavid du Colombier *w++ = grepl[(u >> img->shift[CGreen]) & img->mask[CGreen]];
15807dd7cddfSDavid du Colombier *w++ = rrepl[(u >> img->shift[CRed]) & img->mask[CRed]];
15817dd7cddfSDavid du Colombier }
15827dd7cddfSDavid du Colombier }
15837dd7cddfSDavid du Colombier r += nb;
15847dd7cddfSDavid du Colombier if(r == end)
15857dd7cddfSDavid du Colombier r = begin;
15867dd7cddfSDavid du Colombier }
15877dd7cddfSDavid du Colombier
15886a9fc400SDavid du Colombier b.alpha = copyalpha ? buf : &ones;
15896a9fc400SDavid du Colombier b.rgba = (ulong*)buf;
15907dd7cddfSDavid du Colombier if(alphaonly){
15917dd7cddfSDavid du Colombier b.red = b.grn = b.blu = b.grey = nil;
15926a9fc400SDavid du Colombier if(!copyalpha)
15936a9fc400SDavid du Colombier b.rgba = nil;
15947dd7cddfSDavid du Colombier b.delta = 1;
15957dd7cddfSDavid du Colombier }else if(isgrey || convgrey){
15967dd7cddfSDavid du Colombier b.grey = buf+copyalpha;
15977dd7cddfSDavid du Colombier b.red = b.grn = b.blu = buf+copyalpha;
15987dd7cddfSDavid du Colombier b.delta = copyalpha+1;
159959cc4ca5SDavid du Colombier DBG print("alpha %x grey %x\n", b.alpha ? *b.alpha : 0xFF, *b.grey);
16007dd7cddfSDavid du Colombier }else{
16017dd7cddfSDavid du Colombier b.blu = buf+copyalpha;
16027dd7cddfSDavid du Colombier b.grn = buf+copyalpha+1;
16037dd7cddfSDavid du Colombier b.grey = nil;
16047dd7cddfSDavid du Colombier b.red = buf+copyalpha+2;
16057dd7cddfSDavid du Colombier b.delta = copyalpha+3;
16067dd7cddfSDavid du Colombier }
16077dd7cddfSDavid du Colombier return b;
16087dd7cddfSDavid du Colombier }
160959cc4ca5SDavid du Colombier #undef DBG
16107dd7cddfSDavid du Colombier
16117dd7cddfSDavid du Colombier #define DBG if(0)
16127dd7cddfSDavid du Colombier static void
writebyte(Param * p,uchar * w,Buffer src)16137dd7cddfSDavid du Colombier writebyte(Param *p, uchar *w, Buffer src)
16147dd7cddfSDavid du Colombier {
16157dd7cddfSDavid du Colombier Memimage *img;
16167dd7cddfSDavid du Colombier int i, isalpha, isgrey, nb, delta, dx, adelta;
16177dd7cddfSDavid du Colombier uchar ff, *red, *grn, *blu, *grey, *alpha;
16187dd7cddfSDavid du Colombier ulong u, mask;
16197dd7cddfSDavid du Colombier
16207dd7cddfSDavid du Colombier img = p->img;
16217dd7cddfSDavid du Colombier
16227dd7cddfSDavid du Colombier red = src.red;
16237dd7cddfSDavid du Colombier grn = src.grn;
16247dd7cddfSDavid du Colombier blu = src.blu;
16257dd7cddfSDavid du Colombier alpha = src.alpha;
16267dd7cddfSDavid du Colombier delta = src.delta;
16277dd7cddfSDavid du Colombier grey = src.grey;
16287dd7cddfSDavid du Colombier dx = p->dx;
16297dd7cddfSDavid du Colombier
16307dd7cddfSDavid du Colombier nb = img->depth/8;
16317dd7cddfSDavid du Colombier mask = (nb==4) ? 0 : ~((1<<img->depth)-1);
16327dd7cddfSDavid du Colombier
16337dd7cddfSDavid du Colombier isalpha = img->flags&Falpha;
16347dd7cddfSDavid du Colombier isgrey = img->flags&Fgrey;
16357dd7cddfSDavid du Colombier adelta = src.delta;
16367dd7cddfSDavid du Colombier
16376a9fc400SDavid du Colombier if(isalpha && (alpha == nil || alpha == &ones)){
16387dd7cddfSDavid du Colombier ff = 0xFF;
16397dd7cddfSDavid du Colombier alpha = &ff;
16407dd7cddfSDavid du Colombier adelta = 0;
16417dd7cddfSDavid du Colombier }
16427dd7cddfSDavid du Colombier
16437dd7cddfSDavid du Colombier for(i=0; i<dx; i++){
16447dd7cddfSDavid du Colombier u = w[0] | (w[1]<<8) | (w[2]<<16) | (w[3]<<24);
16457dd7cddfSDavid du Colombier DBG print("u %.8lux...", u);
16467dd7cddfSDavid du Colombier u &= mask;
16477dd7cddfSDavid du Colombier DBG print("&mask %.8lux...", u);
16487dd7cddfSDavid du Colombier if(isgrey){
16497dd7cddfSDavid du Colombier u |= ((*grey >> (8-img->nbits[CGrey])) & img->mask[CGrey]) << img->shift[CGrey];
16507dd7cddfSDavid du Colombier DBG print("|grey %.8lux...", u);
16517dd7cddfSDavid du Colombier grey += delta;
16527dd7cddfSDavid du Colombier }else{
16537dd7cddfSDavid du Colombier u |= ((*red >> (8-img->nbits[CRed])) & img->mask[CRed]) << img->shift[CRed];
16547dd7cddfSDavid du Colombier u |= ((*grn >> (8-img->nbits[CGreen])) & img->mask[CGreen]) << img->shift[CGreen];
16557dd7cddfSDavid du Colombier u |= ((*blu >> (8-img->nbits[CBlue])) & img->mask[CBlue]) << img->shift[CBlue];
16567dd7cddfSDavid du Colombier red += delta;
16577dd7cddfSDavid du Colombier grn += delta;
16587dd7cddfSDavid du Colombier blu += delta;
16597dd7cddfSDavid du Colombier DBG print("|rgb %.8lux...", u);
16607dd7cddfSDavid du Colombier }
16617dd7cddfSDavid du Colombier
16627dd7cddfSDavid du Colombier if(isalpha){
16637dd7cddfSDavid du Colombier u |= ((*alpha >> (8-img->nbits[CAlpha])) & img->mask[CAlpha]) << img->shift[CAlpha];
16647dd7cddfSDavid du Colombier alpha += adelta;
16657dd7cddfSDavid du Colombier DBG print("|alpha %.8lux...", u);
16667dd7cddfSDavid du Colombier }
16677dd7cddfSDavid du Colombier
16687dd7cddfSDavid du Colombier w[0] = u;
16697dd7cddfSDavid du Colombier w[1] = u>>8;
16707dd7cddfSDavid du Colombier w[2] = u>>16;
16717dd7cddfSDavid du Colombier w[3] = u>>24;
16727dd7cddfSDavid du Colombier w += nb;
16737dd7cddfSDavid du Colombier }
16747dd7cddfSDavid du Colombier }
16757dd7cddfSDavid du Colombier #undef DBG
16767dd7cddfSDavid du Colombier
16777dd7cddfSDavid du Colombier static Readfn*
readfn(Memimage * img)16787dd7cddfSDavid du Colombier readfn(Memimage *img)
16797dd7cddfSDavid du Colombier {
16807dd7cddfSDavid du Colombier if(img->depth < 8)
16817dd7cddfSDavid du Colombier return readnbit;
168280ee5cbfSDavid du Colombier if(img->nbits[CMap] == 8)
16837dd7cddfSDavid du Colombier return readcmap;
16847dd7cddfSDavid du Colombier return readbyte;
16857dd7cddfSDavid du Colombier }
16867dd7cddfSDavid du Colombier
16877dd7cddfSDavid du Colombier static Readfn*
readalphafn(Memimage * m)16886a9fc400SDavid du Colombier readalphafn(Memimage *m)
16897dd7cddfSDavid du Colombier {
16906a9fc400SDavid du Colombier USED(m);
16917dd7cddfSDavid du Colombier return readbyte;
16927dd7cddfSDavid du Colombier }
16937dd7cddfSDavid du Colombier
16947dd7cddfSDavid du Colombier static Writefn*
writefn(Memimage * img)16957dd7cddfSDavid du Colombier writefn(Memimage *img)
16967dd7cddfSDavid du Colombier {
16977dd7cddfSDavid du Colombier if(img->depth < 8)
16987dd7cddfSDavid du Colombier return writenbit;
16997dd7cddfSDavid du Colombier if(img->chan == CMAP8)
17007dd7cddfSDavid du Colombier return writecmap;
17017dd7cddfSDavid du Colombier return writebyte;
17027dd7cddfSDavid du Colombier }
17037dd7cddfSDavid du Colombier
17047dd7cddfSDavid du Colombier static void
nullwrite(Param * p,uchar * s,Buffer b)17056a9fc400SDavid du Colombier nullwrite(Param *p, uchar *s, Buffer b)
17067dd7cddfSDavid du Colombier {
17076a9fc400SDavid du Colombier USED(p);
17086a9fc400SDavid du Colombier USED(s);
17096a9fc400SDavid du Colombier USED(b);
17107dd7cddfSDavid du Colombier }
17117dd7cddfSDavid du Colombier
17127dd7cddfSDavid du Colombier static Buffer
readptr(Param * p,uchar * s,int y)17136a9fc400SDavid du Colombier readptr(Param *p, uchar *s, int y)
17147dd7cddfSDavid du Colombier {
17157dd7cddfSDavid du Colombier Buffer b;
17167dd7cddfSDavid du Colombier uchar *q;
17177dd7cddfSDavid du Colombier
17186a9fc400SDavid du Colombier USED(s);
17197dd7cddfSDavid du Colombier q = p->bytermin + y*p->bwidth;
17207dd7cddfSDavid du Colombier b.red = q; /* ptr to data */
17217dd7cddfSDavid du Colombier b.grn = b.blu = b.grey = b.alpha = nil;
17226a9fc400SDavid du Colombier b.rgba = (ulong*)q;
17237dd7cddfSDavid du Colombier b.delta = p->img->depth/8;
17247dd7cddfSDavid du Colombier return b;
17257dd7cddfSDavid du Colombier }
17267dd7cddfSDavid du Colombier
17277dd7cddfSDavid du Colombier static Buffer
boolmemmove(Buffer bdst,Buffer bsrc,Buffer b1,int dx,int i,int o)17286a9fc400SDavid du Colombier boolmemmove(Buffer bdst, Buffer bsrc, Buffer b1, int dx, int i, int o)
17297dd7cddfSDavid du Colombier {
17306a9fc400SDavid du Colombier USED(i);
17316a9fc400SDavid du Colombier USED(o);
17326a9fc400SDavid du Colombier USED(b1);
17336a9fc400SDavid du Colombier USED(bsrc);
17347dd7cddfSDavid du Colombier memmove(bdst.red, bsrc.red, dx*bdst.delta);
17357dd7cddfSDavid du Colombier return bdst;
17367dd7cddfSDavid du Colombier }
17377dd7cddfSDavid du Colombier
17387dd7cddfSDavid du Colombier static Buffer
boolcopy8(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int i,int o)17396a9fc400SDavid du Colombier boolcopy8(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o)
17407dd7cddfSDavid du Colombier {
17417dd7cddfSDavid du Colombier uchar *m, *r, *w, *ew;
17427dd7cddfSDavid du Colombier
17436a9fc400SDavid du Colombier USED(i);
17446a9fc400SDavid du Colombier USED(o);
17457dd7cddfSDavid du Colombier m = bmask.grey;
17467dd7cddfSDavid du Colombier w = bdst.red;
17477dd7cddfSDavid du Colombier r = bsrc.red;
17487dd7cddfSDavid du Colombier ew = w+dx;
17497dd7cddfSDavid du Colombier for(; w < ew; w++,r++)
17507dd7cddfSDavid du Colombier if(*m++)
17517dd7cddfSDavid du Colombier *w = *r;
17527dd7cddfSDavid du Colombier return bdst; /* not used */
17537dd7cddfSDavid du Colombier }
17547dd7cddfSDavid du Colombier
17557dd7cddfSDavid du Colombier static Buffer
boolcopy16(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int i,int o)17566a9fc400SDavid du Colombier boolcopy16(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o)
17577dd7cddfSDavid du Colombier {
17587dd7cddfSDavid du Colombier uchar *m;
17597dd7cddfSDavid du Colombier ushort *r, *w, *ew;
17607dd7cddfSDavid du Colombier
17616a9fc400SDavid du Colombier USED(i);
17626a9fc400SDavid du Colombier USED(o);
17637dd7cddfSDavid du Colombier m = bmask.grey;
17647dd7cddfSDavid du Colombier w = (ushort*)bdst.red;
17657dd7cddfSDavid du Colombier r = (ushort*)bsrc.red;
17667dd7cddfSDavid du Colombier ew = w+dx;
17677dd7cddfSDavid du Colombier for(; w < ew; w++,r++)
17687dd7cddfSDavid du Colombier if(*m++)
17697dd7cddfSDavid du Colombier *w = *r;
17707dd7cddfSDavid du Colombier return bdst; /* not used */
17717dd7cddfSDavid du Colombier }
17727dd7cddfSDavid du Colombier
17737dd7cddfSDavid du Colombier static Buffer
boolcopy24(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int i,int o)17746a9fc400SDavid du Colombier boolcopy24(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o)
17757dd7cddfSDavid du Colombier {
17767dd7cddfSDavid du Colombier uchar *m;
17777dd7cddfSDavid du Colombier uchar *r, *w, *ew;
17787dd7cddfSDavid du Colombier
17796a9fc400SDavid du Colombier USED(i);
17806a9fc400SDavid du Colombier USED(o);
17817dd7cddfSDavid du Colombier m = bmask.grey;
17827dd7cddfSDavid du Colombier w = bdst.red;
17837dd7cddfSDavid du Colombier r = bsrc.red;
17847dd7cddfSDavid du Colombier ew = w+dx*3;
17857dd7cddfSDavid du Colombier while(w < ew){
17867dd7cddfSDavid du Colombier if(*m++){
17877dd7cddfSDavid du Colombier *w++ = *r++;
17887dd7cddfSDavid du Colombier *w++ = *r++;
17897dd7cddfSDavid du Colombier *w++ = *r++;
17907dd7cddfSDavid du Colombier }else{
17917dd7cddfSDavid du Colombier w += 3;
17927dd7cddfSDavid du Colombier r += 3;
17937dd7cddfSDavid du Colombier }
17947dd7cddfSDavid du Colombier }
17957dd7cddfSDavid du Colombier return bdst; /* not used */
17967dd7cddfSDavid du Colombier }
17977dd7cddfSDavid du Colombier
17987dd7cddfSDavid du Colombier static Buffer
boolcopy32(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int i,int o)17996a9fc400SDavid du Colombier boolcopy32(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o)
18007dd7cddfSDavid du Colombier {
18017dd7cddfSDavid du Colombier uchar *m;
18027dd7cddfSDavid du Colombier ulong *r, *w, *ew;
18037dd7cddfSDavid du Colombier
18046a9fc400SDavid du Colombier USED(i);
18056a9fc400SDavid du Colombier USED(o);
18067dd7cddfSDavid du Colombier m = bmask.grey;
18077dd7cddfSDavid du Colombier w = (ulong*)bdst.red;
18087dd7cddfSDavid du Colombier r = (ulong*)bsrc.red;
18097dd7cddfSDavid du Colombier ew = w+dx;
18107dd7cddfSDavid du Colombier for(; w < ew; w++,r++)
18117dd7cddfSDavid du Colombier if(*m++)
18127dd7cddfSDavid du Colombier *w = *r;
18137dd7cddfSDavid du Colombier return bdst; /* not used */
18147dd7cddfSDavid du Colombier }
18157dd7cddfSDavid du Colombier
18167dd7cddfSDavid du Colombier static Buffer
genconv(Param * p,uchar * buf,int y)18177dd7cddfSDavid du Colombier genconv(Param *p, uchar *buf, int y)
18187dd7cddfSDavid du Colombier {
18197dd7cddfSDavid du Colombier Buffer b;
18207dd7cddfSDavid du Colombier int nb;
18217dd7cddfSDavid du Colombier uchar *r, *w, *ew;
18227dd7cddfSDavid du Colombier
18237dd7cddfSDavid du Colombier /* read from source into RGB format in convbuf */
18247dd7cddfSDavid du Colombier b = p->convreadcall(p, p->convbuf, y);
18257dd7cddfSDavid du Colombier
18267dd7cddfSDavid du Colombier /* write RGB format into dst format in buf */
18277dd7cddfSDavid du Colombier p->convwritecall(p->convdpar, buf, b);
18287dd7cddfSDavid du Colombier
18297dd7cddfSDavid du Colombier if(p->convdx){
18307dd7cddfSDavid du Colombier nb = p->convdpar->img->depth/8;
18317dd7cddfSDavid du Colombier r = buf;
18327dd7cddfSDavid du Colombier w = buf+nb*p->dx;
18337dd7cddfSDavid du Colombier ew = buf+nb*p->convdx;
18347dd7cddfSDavid du Colombier while(w<ew)
18357dd7cddfSDavid du Colombier *w++ = *r++;
18367dd7cddfSDavid du Colombier }
18377dd7cddfSDavid du Colombier
18387dd7cddfSDavid du Colombier b.red = buf;
18397dd7cddfSDavid du Colombier b.blu = b.grn = b.grey = b.alpha = nil;
18406a9fc400SDavid du Colombier b.rgba = (ulong*)buf;
18417dd7cddfSDavid du Colombier b.delta = 0;
18427dd7cddfSDavid du Colombier
18437dd7cddfSDavid du Colombier return b;
18447dd7cddfSDavid du Colombier }
18457dd7cddfSDavid du Colombier
18467dd7cddfSDavid du Colombier static Readfn*
convfn(Memimage * dst,Param * dpar,Memimage * src,Param * spar,int * ndrawbuf)1847*2c1878b4SDavid du Colombier convfn(Memimage *dst, Param *dpar, Memimage *src, Param *spar, int *ndrawbuf)
18487dd7cddfSDavid du Colombier {
18497dd7cddfSDavid du Colombier if(dst->chan == src->chan && !(src->flags&Frepl)){
18507dd7cddfSDavid du Colombier //if(drawdebug) iprint("readptr...");
18517dd7cddfSDavid du Colombier return readptr;
18527dd7cddfSDavid du Colombier }
18537dd7cddfSDavid du Colombier
18547dd7cddfSDavid du Colombier if(dst->chan==CMAP8 && (src->chan==GREY1||src->chan==GREY2||src->chan==GREY4)){
18557dd7cddfSDavid du Colombier /* cheat because we know the replicated value is exactly the color map entry. */
18567dd7cddfSDavid du Colombier //if(drawdebug) iprint("Readnbit...");
18577dd7cddfSDavid du Colombier return readnbit;
18587dd7cddfSDavid du Colombier }
18597dd7cddfSDavid du Colombier
18607dd7cddfSDavid du Colombier spar->convreadcall = readfn(src);
18617dd7cddfSDavid du Colombier spar->convwritecall = writefn(dst);
18627dd7cddfSDavid du Colombier spar->convdpar = dpar;
18637dd7cddfSDavid du Colombier
18647dd7cddfSDavid du Colombier /* allocate a conversion buffer */
1865*2c1878b4SDavid du Colombier spar->convbufoff = *ndrawbuf;
1866*2c1878b4SDavid du Colombier *ndrawbuf += spar->dx*4;
18677dd7cddfSDavid du Colombier
18687dd7cddfSDavid du Colombier if(spar->dx > Dx(spar->img->r)){
18697dd7cddfSDavid du Colombier spar->convdx = spar->dx;
18707dd7cddfSDavid du Colombier spar->dx = Dx(spar->img->r);
18717dd7cddfSDavid du Colombier }
18727dd7cddfSDavid du Colombier
18737dd7cddfSDavid du Colombier //if(drawdebug) iprint("genconv...");
18747dd7cddfSDavid du Colombier return genconv;
18757dd7cddfSDavid du Colombier }
18767dd7cddfSDavid du Colombier
18777dd7cddfSDavid du Colombier static ulong
pixelbits(Memimage * i,Point pt)18787dd7cddfSDavid du Colombier pixelbits(Memimage *i, Point pt)
18797dd7cddfSDavid du Colombier {
18807dd7cddfSDavid du Colombier uchar *p;
18817dd7cddfSDavid du Colombier ulong val;
18827dd7cddfSDavid du Colombier int off, bpp, npack;
18837dd7cddfSDavid du Colombier
18847dd7cddfSDavid du Colombier val = 0;
18857dd7cddfSDavid du Colombier p = byteaddr(i, pt);
18867dd7cddfSDavid du Colombier switch(bpp=i->depth){
18877dd7cddfSDavid du Colombier case 1:
18887dd7cddfSDavid du Colombier case 2:
18897dd7cddfSDavid du Colombier case 4:
18907dd7cddfSDavid du Colombier npack = 8/bpp;
18917dd7cddfSDavid du Colombier off = pt.x%npack;
18927dd7cddfSDavid du Colombier val = p[0] >> bpp*(npack-1-off);
18937dd7cddfSDavid du Colombier val &= (1<<bpp)-1;
18947dd7cddfSDavid du Colombier break;
18957dd7cddfSDavid du Colombier case 8:
18967dd7cddfSDavid du Colombier val = p[0];
18977dd7cddfSDavid du Colombier break;
18987dd7cddfSDavid du Colombier case 16:
18997dd7cddfSDavid du Colombier val = p[0]|(p[1]<<8);
19007dd7cddfSDavid du Colombier break;
19017dd7cddfSDavid du Colombier case 24:
19027dd7cddfSDavid du Colombier val = p[0]|(p[1]<<8)|(p[2]<<16);
19037dd7cddfSDavid du Colombier break;
19047dd7cddfSDavid du Colombier case 32:
19057dd7cddfSDavid du Colombier val = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
19067dd7cddfSDavid du Colombier break;
19077dd7cddfSDavid du Colombier }
19087dd7cddfSDavid du Colombier while(bpp<32){
19097dd7cddfSDavid du Colombier val |= val<<bpp;
19107dd7cddfSDavid du Colombier bpp *= 2;
19117dd7cddfSDavid du Colombier }
19127dd7cddfSDavid du Colombier return val;
19137dd7cddfSDavid du Colombier }
19147dd7cddfSDavid du Colombier
19157dd7cddfSDavid du Colombier static Calcfn*
boolcopyfn(Memimage * img,Memimage * mask)19167dd7cddfSDavid du Colombier boolcopyfn(Memimage *img, Memimage *mask)
19177dd7cddfSDavid du Colombier {
19187dd7cddfSDavid du Colombier if(mask->flags&Frepl && Dx(mask->r)==1 && Dy(mask->r)==1 && pixelbits(mask, mask->r.min)==~0)
19197dd7cddfSDavid du Colombier return boolmemmove;
19207dd7cddfSDavid du Colombier
19217dd7cddfSDavid du Colombier switch(img->depth){
19227dd7cddfSDavid du Colombier case 8:
19237dd7cddfSDavid du Colombier return boolcopy8;
19247dd7cddfSDavid du Colombier case 16:
19257dd7cddfSDavid du Colombier return boolcopy16;
19267dd7cddfSDavid du Colombier case 24:
19277dd7cddfSDavid du Colombier return boolcopy24;
19287dd7cddfSDavid du Colombier case 32:
19297dd7cddfSDavid du Colombier return boolcopy32;
19307dd7cddfSDavid du Colombier default:
19317dd7cddfSDavid du Colombier assert(0 /* boolcopyfn */);
19327dd7cddfSDavid du Colombier }
19337dd7cddfSDavid du Colombier return nil;
19347dd7cddfSDavid du Colombier }
19357dd7cddfSDavid du Colombier
19367dd7cddfSDavid du Colombier /*
19377dd7cddfSDavid du Colombier * Optimized draw for filling and scrolling; uses memset and memmove.
19387dd7cddfSDavid du Colombier */
19397dd7cddfSDavid du Colombier static void
memsetb(void * vp,uchar val,int n)19407dd7cddfSDavid du Colombier memsetb(void *vp, uchar val, int n)
19417dd7cddfSDavid du Colombier {
19427dd7cddfSDavid du Colombier uchar *p, *ep;
19437dd7cddfSDavid du Colombier
19447dd7cddfSDavid du Colombier p = vp;
19457dd7cddfSDavid du Colombier ep = p+n;
19467dd7cddfSDavid du Colombier while(p<ep)
19477dd7cddfSDavid du Colombier *p++ = val;
19487dd7cddfSDavid du Colombier }
19497dd7cddfSDavid du Colombier
19507dd7cddfSDavid du Colombier static void
memsets(void * vp,ushort val,int n)19517dd7cddfSDavid du Colombier memsets(void *vp, ushort val, int n)
19527dd7cddfSDavid du Colombier {
19537dd7cddfSDavid du Colombier ushort *p, *ep;
19547dd7cddfSDavid du Colombier
19557dd7cddfSDavid du Colombier p = vp;
19567dd7cddfSDavid du Colombier ep = p+n;
19577dd7cddfSDavid du Colombier while(p<ep)
19587dd7cddfSDavid du Colombier *p++ = val;
19597dd7cddfSDavid du Colombier }
19607dd7cddfSDavid du Colombier
19617dd7cddfSDavid du Colombier static void
memsetl(void * vp,ulong val,int n)19627dd7cddfSDavid du Colombier memsetl(void *vp, ulong val, int n)
19637dd7cddfSDavid du Colombier {
19647dd7cddfSDavid du Colombier ulong *p, *ep;
19657dd7cddfSDavid du Colombier
19667dd7cddfSDavid du Colombier p = vp;
19677dd7cddfSDavid du Colombier ep = p+n;
19687dd7cddfSDavid du Colombier while(p<ep)
19697dd7cddfSDavid du Colombier *p++ = val;
19707dd7cddfSDavid du Colombier }
19717dd7cddfSDavid du Colombier
19727dd7cddfSDavid du Colombier static void
memset24(void * vp,ulong val,int n)19737dd7cddfSDavid du Colombier memset24(void *vp, ulong val, int n)
19747dd7cddfSDavid du Colombier {
19757dd7cddfSDavid du Colombier uchar *p, *ep;
19767dd7cddfSDavid du Colombier uchar a,b,c;
19777dd7cddfSDavid du Colombier
19787dd7cddfSDavid du Colombier p = vp;
19797dd7cddfSDavid du Colombier ep = p+3*n;
19807dd7cddfSDavid du Colombier a = val;
19817dd7cddfSDavid du Colombier b = val>>8;
19827dd7cddfSDavid du Colombier c = val>>16;
19837dd7cddfSDavid du Colombier while(p<ep){
19847dd7cddfSDavid du Colombier *p++ = a;
19857dd7cddfSDavid du Colombier *p++ = b;
19867dd7cddfSDavid du Colombier *p++ = c;
19877dd7cddfSDavid du Colombier }
19887dd7cddfSDavid du Colombier }
19897dd7cddfSDavid du Colombier
19907dd7cddfSDavid du Colombier static ulong
imgtorgba(Memimage * img,ulong val)19917dd7cddfSDavid du Colombier imgtorgba(Memimage *img, ulong val)
19927dd7cddfSDavid du Colombier {
19937dd7cddfSDavid du Colombier uchar r, g, b, a;
19947dd7cddfSDavid du Colombier int nb, ov, v;
19957dd7cddfSDavid du Colombier ulong chan;
19967dd7cddfSDavid du Colombier uchar *p;
19977dd7cddfSDavid du Colombier
19987dd7cddfSDavid du Colombier a = 0xFF;
19997dd7cddfSDavid du Colombier r = g = b = 0xAA; /* garbage */
20007dd7cddfSDavid du Colombier for(chan=img->chan; chan; chan>>=8){
20017dd7cddfSDavid du Colombier nb = NBITS(chan);
20027dd7cddfSDavid du Colombier ov = v = val&((1<<nb)-1);
20037dd7cddfSDavid du Colombier val >>= nb;
20047dd7cddfSDavid du Colombier
20057dd7cddfSDavid du Colombier while(nb < 8){
20067dd7cddfSDavid du Colombier v |= v<<nb;
20077dd7cddfSDavid du Colombier nb *= 2;
20087dd7cddfSDavid du Colombier }
20097dd7cddfSDavid du Colombier v >>= (nb-8);
20107dd7cddfSDavid du Colombier
20117dd7cddfSDavid du Colombier switch(TYPE(chan)){
20127dd7cddfSDavid du Colombier case CRed:
20137dd7cddfSDavid du Colombier r = v;
20147dd7cddfSDavid du Colombier break;
20157dd7cddfSDavid du Colombier case CGreen:
20167dd7cddfSDavid du Colombier g = v;
20177dd7cddfSDavid du Colombier break;
20187dd7cddfSDavid du Colombier case CBlue:
20197dd7cddfSDavid du Colombier b = v;
20207dd7cddfSDavid du Colombier break;
20217dd7cddfSDavid du Colombier case CAlpha:
20227dd7cddfSDavid du Colombier a = v;
20237dd7cddfSDavid du Colombier break;
20247dd7cddfSDavid du Colombier case CGrey:
20257dd7cddfSDavid du Colombier r = g = b = v;
20267dd7cddfSDavid du Colombier break;
20277dd7cddfSDavid du Colombier case CMap:
20287dd7cddfSDavid du Colombier p = img->cmap->cmap2rgb+3*ov;
20297dd7cddfSDavid du Colombier r = *p++;
20307dd7cddfSDavid du Colombier g = *p++;
20317dd7cddfSDavid du Colombier b = *p;
20327dd7cddfSDavid du Colombier break;
20337dd7cddfSDavid du Colombier }
20347dd7cddfSDavid du Colombier }
20357dd7cddfSDavid du Colombier return (r<<24)|(g<<16)|(b<<8)|a;
20367dd7cddfSDavid du Colombier }
20377dd7cddfSDavid du Colombier
20387dd7cddfSDavid du Colombier static ulong
rgbatoimg(Memimage * img,ulong rgba)20397dd7cddfSDavid du Colombier rgbatoimg(Memimage *img, ulong rgba)
20407dd7cddfSDavid du Colombier {
20417dd7cddfSDavid du Colombier ulong chan;
20427dd7cddfSDavid du Colombier int d, nb;
20437dd7cddfSDavid du Colombier ulong v;
20447dd7cddfSDavid du Colombier uchar *p, r, g, b, a, m;
20457dd7cddfSDavid du Colombier
20467dd7cddfSDavid du Colombier v = 0;
20477dd7cddfSDavid du Colombier r = rgba>>24;
20487dd7cddfSDavid du Colombier g = rgba>>16;
20497dd7cddfSDavid du Colombier b = rgba>>8;
20507dd7cddfSDavid du Colombier a = rgba;
20517dd7cddfSDavid du Colombier d = 0;
20527dd7cddfSDavid du Colombier for(chan=img->chan; chan; chan>>=8){
20537dd7cddfSDavid du Colombier nb = NBITS(chan);
20547dd7cddfSDavid du Colombier switch(TYPE(chan)){
20557dd7cddfSDavid du Colombier case CRed:
20567dd7cddfSDavid du Colombier v |= (r>>(8-nb))<<d;
20577dd7cddfSDavid du Colombier break;
20587dd7cddfSDavid du Colombier case CGreen:
20597dd7cddfSDavid du Colombier v |= (g>>(8-nb))<<d;
20607dd7cddfSDavid du Colombier break;
20617dd7cddfSDavid du Colombier case CBlue:
20627dd7cddfSDavid du Colombier v |= (b>>(8-nb))<<d;
20637dd7cddfSDavid du Colombier break;
20647dd7cddfSDavid du Colombier case CAlpha:
20657dd7cddfSDavid du Colombier v |= (a>>(8-nb))<<d;
20667dd7cddfSDavid du Colombier break;
20677dd7cddfSDavid du Colombier case CMap:
20687dd7cddfSDavid du Colombier p = img->cmap->rgb2cmap;
20697dd7cddfSDavid du Colombier m = p[(r>>4)*256+(g>>4)*16+(b>>4)];
207059cc4ca5SDavid du Colombier v |= (m>>(8-nb))<<d;
20717dd7cddfSDavid du Colombier break;
20727dd7cddfSDavid du Colombier case CGrey:
20737dd7cddfSDavid du Colombier m = RGB2K(r,g,b);
207459cc4ca5SDavid du Colombier v |= (m>>(8-nb))<<d;
20757dd7cddfSDavid du Colombier break;
20767dd7cddfSDavid du Colombier }
20777dd7cddfSDavid du Colombier d += nb;
20787dd7cddfSDavid du Colombier }
20797dd7cddfSDavid du Colombier // print("rgba2img %.8lux = %.*lux\n", rgba, 2*d/8, v);
20807dd7cddfSDavid du Colombier return v;
20817dd7cddfSDavid du Colombier }
20827dd7cddfSDavid du Colombier
208380ee5cbfSDavid du Colombier #define DBG if(0)
20847dd7cddfSDavid du Colombier static int
memoptdraw(Memdrawparam * par)20857dd7cddfSDavid du Colombier memoptdraw(Memdrawparam *par)
20867dd7cddfSDavid du Colombier {
20876a9fc400SDavid du Colombier int m, y, dy, dx, op;
20887dd7cddfSDavid du Colombier ulong v;
20897dd7cddfSDavid du Colombier Memimage *src;
20907dd7cddfSDavid du Colombier Memimage *dst;
20917dd7cddfSDavid du Colombier
20927dd7cddfSDavid du Colombier dx = Dx(par->r);
20937dd7cddfSDavid du Colombier dy = Dy(par->r);
20947dd7cddfSDavid du Colombier src = par->src;
20957dd7cddfSDavid du Colombier dst = par->dst;
20966a9fc400SDavid du Colombier op = par->op;
20977dd7cddfSDavid du Colombier
209880ee5cbfSDavid du Colombier DBG print("state %lux mval %lux dd %d\n", par->state, par->mval, dst->depth);
20997dd7cddfSDavid du Colombier /*
21007dd7cddfSDavid du Colombier * If we have an opaque mask and source is one opaque pixel we can convert to the
21017dd7cddfSDavid du Colombier * destination format and just replicate with memset.
21027dd7cddfSDavid du Colombier */
21037dd7cddfSDavid du Colombier m = Simplesrc|Simplemask|Fullmask;
21046a9fc400SDavid du Colombier if((par->state&m)==m && (par->srgba&0xFF) == 0xFF && (op ==S || op == SoverD)){
21057dd7cddfSDavid du Colombier uchar *dp, p[4];
210659cc4ca5SDavid du Colombier int d, dwid, ppb, np, nb;
21077dd7cddfSDavid du Colombier uchar lm, rm;
21087dd7cddfSDavid du Colombier
210980ee5cbfSDavid du Colombier DBG print("memopt, dst %p, dst->data->bdata %p\n", dst, dst->data->bdata);
21107dd7cddfSDavid du Colombier dwid = dst->width*sizeof(ulong);
21117dd7cddfSDavid du Colombier dp = byteaddr(dst, par->r.min);
21127dd7cddfSDavid du Colombier v = par->sdval;
211380ee5cbfSDavid du Colombier DBG print("sdval %lud, depth %d\n", v, dst->depth);
21147dd7cddfSDavid du Colombier switch(dst->depth){
21157dd7cddfSDavid du Colombier case 1:
21167dd7cddfSDavid du Colombier case 2:
21177dd7cddfSDavid du Colombier case 4:
211859cc4ca5SDavid du Colombier for(d=dst->depth; d<8; d*=2)
211959cc4ca5SDavid du Colombier v |= (v<<d);
21207dd7cddfSDavid du Colombier ppb = 8/dst->depth; /* pixels per byte */
21217dd7cddfSDavid du Colombier m = ppb-1;
21227dd7cddfSDavid du Colombier /* left edge */
21237dd7cddfSDavid du Colombier np = par->r.min.x&m; /* no. pixels unused on left side of word */
21247dd7cddfSDavid du Colombier dx -= (ppb-np);
21257dd7cddfSDavid du Colombier nb = 8 - np * dst->depth; /* no. bits used on right side of word */
21267dd7cddfSDavid du Colombier lm = (1<<nb)-1;
212780ee5cbfSDavid du Colombier DBG print("np %d x %d nb %d lm %ux ppb %d m %ux\n", np, par->r.min.x, nb, lm, ppb, m);
21287dd7cddfSDavid du Colombier
21297dd7cddfSDavid du Colombier /* right edge */
21307dd7cddfSDavid du Colombier np = par->r.max.x&m; /* no. pixels used on left side of word */
21317dd7cddfSDavid du Colombier dx -= np;
21327dd7cddfSDavid du Colombier nb = 8 - np * dst->depth; /* no. bits unused on right side of word */
21337dd7cddfSDavid du Colombier rm = ~((1<<nb)-1);
213480ee5cbfSDavid du Colombier DBG print("np %d x %d nb %d rm %ux ppb %d m %ux\n", np, par->r.max.x, nb, rm, ppb, m);
21357dd7cddfSDavid du Colombier
213680ee5cbfSDavid du Colombier DBG print("dx %d Dx %d\n", dx, Dx(par->r));
21377dd7cddfSDavid du Colombier /* lm, rm are masks that are 1 where we should touch the bits */
21387dd7cddfSDavid du Colombier if(dx < 0){ /* just one byte */
21397dd7cddfSDavid du Colombier lm &= rm;
21407dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid)
21417dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & lm;
21427dd7cddfSDavid du Colombier }else if(dx == 0){ /* no full bytes */
21437dd7cddfSDavid du Colombier if(lm)
21447dd7cddfSDavid du Colombier dwid--;
21457dd7cddfSDavid du Colombier
21467dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid){
21477dd7cddfSDavid du Colombier if(lm){
214880ee5cbfSDavid du Colombier DBG print("dp %p v %lux lm %ux (v ^ *dp) & lm %lux\n", dp, v, lm, (v^*dp)&lm);
21497dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & lm;
21507dd7cddfSDavid du Colombier dp++;
21517dd7cddfSDavid du Colombier }
21527dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & rm;
21537dd7cddfSDavid du Colombier }
21547dd7cddfSDavid du Colombier }else{ /* full bytes in middle */
21557dd7cddfSDavid du Colombier dx /= ppb;
21567dd7cddfSDavid du Colombier if(lm)
21577dd7cddfSDavid du Colombier dwid--;
21587dd7cddfSDavid du Colombier dwid -= dx;
21597dd7cddfSDavid du Colombier
21607dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid){
21617dd7cddfSDavid du Colombier if(lm){
21627dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & lm;
21637dd7cddfSDavid du Colombier dp++;
21647dd7cddfSDavid du Colombier }
21657dd7cddfSDavid du Colombier memset(dp, v, dx);
21667dd7cddfSDavid du Colombier dp += dx;
21677dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & rm;
21687dd7cddfSDavid du Colombier }
21697dd7cddfSDavid du Colombier }
21707dd7cddfSDavid du Colombier return 1;
21717dd7cddfSDavid du Colombier case 8:
21727dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid)
21737dd7cddfSDavid du Colombier memset(dp, v, dx);
21747dd7cddfSDavid du Colombier return 1;
21757dd7cddfSDavid du Colombier case 16:
21767dd7cddfSDavid du Colombier p[0] = v; /* make little endian */
21777dd7cddfSDavid du Colombier p[1] = v>>8;
21787dd7cddfSDavid du Colombier v = *(ushort*)p;
217980ee5cbfSDavid du Colombier DBG print("dp=%p; dx=%d; for(y=0; y<%d; y++, dp+=%d)\nmemsets(dp, v, dx);\n",
218080ee5cbfSDavid du Colombier dp, dx, dy, dwid);
21817dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid)
21827dd7cddfSDavid du Colombier memsets(dp, v, dx);
21837dd7cddfSDavid du Colombier return 1;
21847dd7cddfSDavid du Colombier case 24:
21857dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid)
21867dd7cddfSDavid du Colombier memset24(dp, v, dx);
21877dd7cddfSDavid du Colombier return 1;
21887dd7cddfSDavid du Colombier case 32:
21897dd7cddfSDavid du Colombier p[0] = v; /* make little endian */
21907dd7cddfSDavid du Colombier p[1] = v>>8;
21917dd7cddfSDavid du Colombier p[2] = v>>16;
21927dd7cddfSDavid du Colombier p[3] = v>>24;
21937dd7cddfSDavid du Colombier v = *(ulong*)p;
21947dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid)
21957dd7cddfSDavid du Colombier memsetl(dp, v, dx);
21967dd7cddfSDavid du Colombier return 1;
21977dd7cddfSDavid du Colombier default:
21987dd7cddfSDavid du Colombier assert(0 /* bad dest depth in memoptdraw */);
21997dd7cddfSDavid du Colombier }
22007dd7cddfSDavid du Colombier }
22017dd7cddfSDavid du Colombier
22027dd7cddfSDavid du Colombier /*
22037dd7cddfSDavid du Colombier * If no source alpha, an opaque mask, we can just copy the
22047dd7cddfSDavid du Colombier * source onto the destination. If the channels are the same and
22057dd7cddfSDavid du Colombier * the source is not replicated, memmove suffices.
22067dd7cddfSDavid du Colombier */
22077dd7cddfSDavid du Colombier m = Simplemask|Fullmask;
22087dd7cddfSDavid du Colombier if((par->state&(m|Replsrc))==m && src->depth >= 8
22096a9fc400SDavid du Colombier && src->chan == dst->chan && !(src->flags&Falpha) && (op == S || op == SoverD)){
22107dd7cddfSDavid du Colombier uchar *sp, *dp;
22117dd7cddfSDavid du Colombier long swid, dwid, nb;
22127dd7cddfSDavid du Colombier int dir;
22137dd7cddfSDavid du Colombier
22147dd7cddfSDavid du Colombier if(src->data == dst->data && byteaddr(dst, par->r.min) > byteaddr(src, par->sr.min))
22157dd7cddfSDavid du Colombier dir = -1;
22167dd7cddfSDavid du Colombier else
22177dd7cddfSDavid du Colombier dir = 1;
22187dd7cddfSDavid du Colombier
22197dd7cddfSDavid du Colombier swid = src->width*sizeof(ulong);
22207dd7cddfSDavid du Colombier dwid = dst->width*sizeof(ulong);
22217dd7cddfSDavid du Colombier sp = byteaddr(src, par->sr.min);
22227dd7cddfSDavid du Colombier dp = byteaddr(dst, par->r.min);
22237dd7cddfSDavid du Colombier if(dir == -1){
22247dd7cddfSDavid du Colombier sp += (dy-1)*swid;
22257dd7cddfSDavid du Colombier dp += (dy-1)*dwid;
22267dd7cddfSDavid du Colombier swid = -swid;
22277dd7cddfSDavid du Colombier dwid = -dwid;
22287dd7cddfSDavid du Colombier }
22297dd7cddfSDavid du Colombier nb = (dx*src->depth)/8;
22307dd7cddfSDavid du Colombier for(y=0; y<dy; y++, sp+=swid, dp+=dwid)
22317dd7cddfSDavid du Colombier memmove(dp, sp, nb);
22327dd7cddfSDavid du Colombier return 1;
22337dd7cddfSDavid du Colombier }
22347dd7cddfSDavid du Colombier
22357dd7cddfSDavid du Colombier /*
22367dd7cddfSDavid du Colombier * If we have a 1-bit mask, 1-bit source, and 1-bit destination, and
22377dd7cddfSDavid du Colombier * they're all bit aligned, we can just use bit operators. This happens
22387dd7cddfSDavid du Colombier * when we're manipulating boolean masks, e.g. in the arc code.
22397dd7cddfSDavid du Colombier */
22407dd7cddfSDavid du Colombier if((par->state&(Simplemask|Simplesrc|Replmask|Replsrc))==0
22417dd7cddfSDavid du Colombier && dst->chan==GREY1 && src->chan==GREY1 && par->mask->chan==GREY1
22427dd7cddfSDavid du Colombier && (par->r.min.x&7)==(par->sr.min.x&7) && (par->r.min.x&7)==(par->mr.min.x&7)){
22437dd7cddfSDavid du Colombier uchar *sp, *dp, *mp;
22447dd7cddfSDavid du Colombier uchar lm, rm;
22457dd7cddfSDavid du Colombier long swid, dwid, mwid;
22467dd7cddfSDavid du Colombier int i, x, dir;
22477dd7cddfSDavid du Colombier
22487dd7cddfSDavid du Colombier sp = byteaddr(src, par->sr.min);
22497dd7cddfSDavid du Colombier dp = byteaddr(dst, par->r.min);
22507dd7cddfSDavid du Colombier mp = byteaddr(par->mask, par->mr.min);
22517dd7cddfSDavid du Colombier swid = src->width*sizeof(ulong);
22527dd7cddfSDavid du Colombier dwid = dst->width*sizeof(ulong);
22537dd7cddfSDavid du Colombier mwid = par->mask->width*sizeof(ulong);
22547dd7cddfSDavid du Colombier
22557dd7cddfSDavid du Colombier if(src->data == dst->data && byteaddr(dst, par->r.min) > byteaddr(src, par->sr.min)){
22567dd7cddfSDavid du Colombier dir = -1;
22577dd7cddfSDavid du Colombier }else
22587dd7cddfSDavid du Colombier dir = 1;
22597dd7cddfSDavid du Colombier
22607dd7cddfSDavid du Colombier lm = 0xFF>>(par->r.min.x&7);
22617dd7cddfSDavid du Colombier rm = 0xFF<<(8-(par->r.max.x&7));
22627dd7cddfSDavid du Colombier dx -= (8-(par->r.min.x&7)) + (par->r.max.x&7);
22637dd7cddfSDavid du Colombier
22647dd7cddfSDavid du Colombier if(dx < 0){ /* one byte wide */
22657dd7cddfSDavid du Colombier lm &= rm;
22667dd7cddfSDavid du Colombier if(dir == -1){
22677dd7cddfSDavid du Colombier dp += dwid*(dy-1);
22687dd7cddfSDavid du Colombier sp += swid*(dy-1);
22697dd7cddfSDavid du Colombier mp += mwid*(dy-1);
22707dd7cddfSDavid du Colombier dwid = -dwid;
22717dd7cddfSDavid du Colombier swid = -swid;
22727dd7cddfSDavid du Colombier mwid = -mwid;
22737dd7cddfSDavid du Colombier }
22747dd7cddfSDavid du Colombier for(y=0; y<dy; y++){
22757dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp) & *mp & lm;
22767dd7cddfSDavid du Colombier dp += dwid;
22777dd7cddfSDavid du Colombier sp += swid;
22787dd7cddfSDavid du Colombier mp += mwid;
22797dd7cddfSDavid du Colombier }
22807dd7cddfSDavid du Colombier return 1;
22817dd7cddfSDavid du Colombier }
22827dd7cddfSDavid du Colombier
22837dd7cddfSDavid du Colombier dx /= 8;
22847dd7cddfSDavid du Colombier if(dir == 1){
22857dd7cddfSDavid du Colombier i = (lm!=0)+dx+(rm!=0);
22867dd7cddfSDavid du Colombier mwid -= i;
22877dd7cddfSDavid du Colombier swid -= i;
22887dd7cddfSDavid du Colombier dwid -= i;
22897dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid, sp+=swid, mp+=mwid){
22907dd7cddfSDavid du Colombier if(lm){
22917dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp++) & *mp++ & lm;
22927dd7cddfSDavid du Colombier dp++;
22937dd7cddfSDavid du Colombier }
22947dd7cddfSDavid du Colombier for(x=0; x<dx; x++){
22957dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp++) & *mp++;
22967dd7cddfSDavid du Colombier dp++;
22977dd7cddfSDavid du Colombier }
22987dd7cddfSDavid du Colombier if(rm){
22997dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp++) & *mp++ & rm;
23007dd7cddfSDavid du Colombier dp++;
23017dd7cddfSDavid du Colombier }
23027dd7cddfSDavid du Colombier }
23037dd7cddfSDavid du Colombier return 1;
23047dd7cddfSDavid du Colombier }else{
23057dd7cddfSDavid du Colombier /* dir == -1 */
23067dd7cddfSDavid du Colombier i = (lm!=0)+dx+(rm!=0);
23077dd7cddfSDavid du Colombier dp += dwid*(dy-1)+i-1;
23087dd7cddfSDavid du Colombier sp += swid*(dy-1)+i-1;
23097dd7cddfSDavid du Colombier mp += mwid*(dy-1)+i-1;
23107dd7cddfSDavid du Colombier dwid = -dwid+i;
23117dd7cddfSDavid du Colombier swid = -swid+i;
23127dd7cddfSDavid du Colombier mwid = -mwid+i;
23137dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid, sp+=swid, mp+=mwid){
23147dd7cddfSDavid du Colombier if(rm){
23157dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp--) & *mp-- & rm;
23167dd7cddfSDavid du Colombier dp--;
23177dd7cddfSDavid du Colombier }
23187dd7cddfSDavid du Colombier for(x=0; x<dx; x++){
23197dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp--) & *mp--;
23207dd7cddfSDavid du Colombier dp--;
23217dd7cddfSDavid du Colombier }
23227dd7cddfSDavid du Colombier if(lm){
23237dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp--) & *mp-- & lm;
23247dd7cddfSDavid du Colombier dp--;
23257dd7cddfSDavid du Colombier }
23267dd7cddfSDavid du Colombier }
23277dd7cddfSDavid du Colombier }
23287dd7cddfSDavid du Colombier return 1;
23297dd7cddfSDavid du Colombier }
23307dd7cddfSDavid du Colombier return 0;
23317dd7cddfSDavid du Colombier }
233280ee5cbfSDavid du Colombier #undef DBG
23337dd7cddfSDavid du Colombier
23347dd7cddfSDavid du Colombier /*
23357dd7cddfSDavid du Colombier * Boolean character drawing.
23367dd7cddfSDavid du Colombier * Solid opaque color through a 1-bit greyscale mask.
23377dd7cddfSDavid du Colombier */
23387dd7cddfSDavid du Colombier #define DBG if(0)
23397dd7cddfSDavid du Colombier static int
chardraw(Memdrawparam * par)23407dd7cddfSDavid du Colombier chardraw(Memdrawparam *par)
23417dd7cddfSDavid du Colombier {
23427dd7cddfSDavid du Colombier ulong bits;
23436a9fc400SDavid du Colombier int i, ddepth, dy, dx, x, bx, ex, y, npack, bsh, depth, op;
23447dd7cddfSDavid du Colombier ulong v, maskwid, dstwid;
23457dd7cddfSDavid du Colombier uchar *wp, *rp, *q, *wc;
23467dd7cddfSDavid du Colombier ushort *ws;
23477dd7cddfSDavid du Colombier ulong *wl;
23487dd7cddfSDavid du Colombier uchar sp[4];
23497dd7cddfSDavid du Colombier Rectangle r, mr;
23507dd7cddfSDavid du Colombier Memimage *mask, *src, *dst;
23517dd7cddfSDavid du Colombier
23527dd7cddfSDavid du Colombier if(0) if(drawdebug) iprint("chardraw? mf %lux md %d sf %lux dxs %d dys %d dd %d ddat %p sdat %p\n",
23537dd7cddfSDavid du Colombier par->mask->flags, par->mask->depth, par->src->flags,
23547dd7cddfSDavid du Colombier Dx(par->src->r), Dy(par->src->r), par->dst->depth, par->dst->data, par->src->data);
23557dd7cddfSDavid du Colombier
23567dd7cddfSDavid du Colombier mask = par->mask;
23577dd7cddfSDavid du Colombier src = par->src;
23587dd7cddfSDavid du Colombier dst = par->dst;
23597dd7cddfSDavid du Colombier r = par->r;
23607dd7cddfSDavid du Colombier mr = par->mr;
23616a9fc400SDavid du Colombier op = par->op;
23627dd7cddfSDavid du Colombier
23637dd7cddfSDavid du Colombier if((par->state&(Replsrc|Simplesrc|Replmask)) != (Replsrc|Simplesrc)
23646a9fc400SDavid du Colombier || mask->depth != 1 || src->flags&Falpha || dst->depth<8 || dst->data==src->data
23656a9fc400SDavid du Colombier || op != SoverD)
23667dd7cddfSDavid du Colombier return 0;
23677dd7cddfSDavid du Colombier
23687dd7cddfSDavid du Colombier //if(drawdebug) iprint("chardraw...");
23697dd7cddfSDavid du Colombier
23707dd7cddfSDavid du Colombier depth = mask->depth;
23717dd7cddfSDavid du Colombier maskwid = mask->width*sizeof(ulong);
23727dd7cddfSDavid du Colombier rp = byteaddr(mask, mr.min);
23737dd7cddfSDavid du Colombier npack = 8/depth;
23747dd7cddfSDavid du Colombier bsh = (mr.min.x % npack) * depth;
23757dd7cddfSDavid du Colombier
23767dd7cddfSDavid du Colombier wp = byteaddr(dst, r.min);
23777dd7cddfSDavid du Colombier dstwid = dst->width*sizeof(ulong);
23787dd7cddfSDavid du Colombier DBG print("bsh %d\n", bsh);
23797dd7cddfSDavid du Colombier dy = Dy(r);
23807dd7cddfSDavid du Colombier dx = Dx(r);
23817dd7cddfSDavid du Colombier
23827dd7cddfSDavid du Colombier ddepth = dst->depth;
23837dd7cddfSDavid du Colombier
23847dd7cddfSDavid du Colombier /*
23857dd7cddfSDavid du Colombier * for loop counts from bsh to bsh+dx
23867dd7cddfSDavid du Colombier *
23877dd7cddfSDavid du Colombier * we want the bottom bits to be the amount
23887dd7cddfSDavid du Colombier * to shift the pixels down, so for n≡0 (mod 8) we want
23897dd7cddfSDavid du Colombier * bottom bits 7. for n≡1, 6, etc.
23907dd7cddfSDavid du Colombier * the bits come from -n-1.
23917dd7cddfSDavid du Colombier */
23927dd7cddfSDavid du Colombier
23937dd7cddfSDavid du Colombier bx = -bsh-1;
23947dd7cddfSDavid du Colombier ex = -bsh-1-dx;
23957dd7cddfSDavid du Colombier SET(bits);
23967dd7cddfSDavid du Colombier v = par->sdval;
23977dd7cddfSDavid du Colombier
23987dd7cddfSDavid du Colombier /* make little endian */
23997dd7cddfSDavid du Colombier sp[0] = v;
24007dd7cddfSDavid du Colombier sp[1] = v>>8;
24017dd7cddfSDavid du Colombier sp[2] = v>>16;
24027dd7cddfSDavid du Colombier sp[3] = v>>24;
24037dd7cddfSDavid du Colombier
24047dd7cddfSDavid du Colombier //print("sp %x %x %x %x\n", sp[0], sp[1], sp[2], sp[3]);
24057dd7cddfSDavid du Colombier for(y=0; y<dy; y++, rp+=maskwid, wp+=dstwid){
24067dd7cddfSDavid du Colombier q = rp;
24077dd7cddfSDavid du Colombier if(bsh)
24087dd7cddfSDavid du Colombier bits = *q++;
24097dd7cddfSDavid du Colombier switch(ddepth){
24107dd7cddfSDavid du Colombier case 8:
24117dd7cddfSDavid du Colombier //if(drawdebug) iprint("8loop...");
24127dd7cddfSDavid du Colombier wc = wp;
24137dd7cddfSDavid du Colombier for(x=bx; x>ex; x--, wc++){
24147dd7cddfSDavid du Colombier i = x&7;
24157dd7cddfSDavid du Colombier if(i == 8-1)
24167dd7cddfSDavid du Colombier bits = *q++;
24177dd7cddfSDavid du Colombier DBG print("bits %lux sh %d...", bits, i);
24187dd7cddfSDavid du Colombier if((bits>>i)&1)
24197dd7cddfSDavid du Colombier *wc = v;
24207dd7cddfSDavid du Colombier }
24217dd7cddfSDavid du Colombier break;
24227dd7cddfSDavid du Colombier case 16:
24237dd7cddfSDavid du Colombier ws = (ushort*)wp;
24247dd7cddfSDavid du Colombier v = *(ushort*)sp;
24257dd7cddfSDavid du Colombier for(x=bx; x>ex; x--, ws++){
24267dd7cddfSDavid du Colombier i = x&7;
24277dd7cddfSDavid du Colombier if(i == 8-1)
24287dd7cddfSDavid du Colombier bits = *q++;
24297dd7cddfSDavid du Colombier DBG print("bits %lux sh %d...", bits, i);
24307dd7cddfSDavid du Colombier if((bits>>i)&1)
24317dd7cddfSDavid du Colombier *ws = v;
24327dd7cddfSDavid du Colombier }
24337dd7cddfSDavid du Colombier break;
24347dd7cddfSDavid du Colombier case 24:
24357dd7cddfSDavid du Colombier wc = wp;
24367dd7cddfSDavid du Colombier for(x=bx; x>ex; x--, wc+=3){
24377dd7cddfSDavid du Colombier i = x&7;
24387dd7cddfSDavid du Colombier if(i == 8-1)
24397dd7cddfSDavid du Colombier bits = *q++;
24407dd7cddfSDavid du Colombier DBG print("bits %lux sh %d...", bits, i);
24417dd7cddfSDavid du Colombier if((bits>>i)&1){
24427dd7cddfSDavid du Colombier wc[0] = sp[0];
24437dd7cddfSDavid du Colombier wc[1] = sp[1];
24447dd7cddfSDavid du Colombier wc[2] = sp[2];
24457dd7cddfSDavid du Colombier }
24467dd7cddfSDavid du Colombier }
24477dd7cddfSDavid du Colombier break;
24487dd7cddfSDavid du Colombier case 32:
24497dd7cddfSDavid du Colombier wl = (ulong*)wp;
24507dd7cddfSDavid du Colombier v = *(ulong*)sp;
24517dd7cddfSDavid du Colombier for(x=bx; x>ex; x--, wl++){
24527dd7cddfSDavid du Colombier i = x&7;
24537dd7cddfSDavid du Colombier if(i == 8-1)
24547dd7cddfSDavid du Colombier bits = *q++;
24557dd7cddfSDavid du Colombier DBG iprint("bits %lux sh %d...", bits, i);
24567dd7cddfSDavid du Colombier if((bits>>i)&1)
24577dd7cddfSDavid du Colombier *wl = v;
24587dd7cddfSDavid du Colombier }
24597dd7cddfSDavid du Colombier break;
24607dd7cddfSDavid du Colombier }
24617dd7cddfSDavid du Colombier }
24627dd7cddfSDavid du Colombier
24637dd7cddfSDavid du Colombier DBG print("\n");
24647dd7cddfSDavid du Colombier return 1;
24657dd7cddfSDavid du Colombier }
24667dd7cddfSDavid du Colombier #undef DBG
24677dd7cddfSDavid du Colombier
24687dd7cddfSDavid du Colombier
24697dd7cddfSDavid du Colombier /*
24707dd7cddfSDavid du Colombier * Fill entire byte with replicated (if necessary) copy of source pixel,
24717dd7cddfSDavid du Colombier * assuming destination ldepth is >= source ldepth.
24727dd7cddfSDavid du Colombier *
24737dd7cddfSDavid du Colombier * This code is just plain wrong for >8bpp.
24747dd7cddfSDavid du Colombier *
24757dd7cddfSDavid du Colombier ulong
24767dd7cddfSDavid du Colombier membyteval(Memimage *src)
24777dd7cddfSDavid du Colombier {
24787dd7cddfSDavid du Colombier int i, val, bpp;
24797dd7cddfSDavid du Colombier uchar uc;
24807dd7cddfSDavid du Colombier
24817dd7cddfSDavid du Colombier unloadmemimage(src, src->r, &uc, 1);
24827dd7cddfSDavid du Colombier bpp = src->depth;
24837dd7cddfSDavid du Colombier uc <<= (src->r.min.x&(7/src->depth))*src->depth;
24847dd7cddfSDavid du Colombier uc &= ~(0xFF>>bpp);
24857dd7cddfSDavid du Colombier /* pixel value is now in high part of byte. repeat throughout byte
24867dd7cddfSDavid du Colombier val = uc;
24877dd7cddfSDavid du Colombier for(i=bpp; i<8; i<<=1)
24887dd7cddfSDavid du Colombier val |= val>>i;
24897dd7cddfSDavid du Colombier return val;
24907dd7cddfSDavid du Colombier }
24917dd7cddfSDavid du Colombier *
24927dd7cddfSDavid du Colombier */
249359cc4ca5SDavid du Colombier
249459cc4ca5SDavid du Colombier void
memfillcolor(Memimage * i,ulong val)249559cc4ca5SDavid du Colombier memfillcolor(Memimage *i, ulong val)
249659cc4ca5SDavid du Colombier {
249759cc4ca5SDavid du Colombier ulong bits;
249859cc4ca5SDavid du Colombier int d, y;
249959cc4ca5SDavid du Colombier
250059cc4ca5SDavid du Colombier if(val == DNofill)
250159cc4ca5SDavid du Colombier return;
250259cc4ca5SDavid du Colombier
250359cc4ca5SDavid du Colombier bits = rgbatoimg(i, val);
250459cc4ca5SDavid du Colombier switch(i->depth){
250559cc4ca5SDavid du Colombier case 24: /* 24-bit images suck */
250659cc4ca5SDavid du Colombier for(y=i->r.min.y; y<i->r.max.y; y++)
250759cc4ca5SDavid du Colombier memset24(byteaddr(i, Pt(i->r.min.x, y)), bits, Dx(i->r));
250859cc4ca5SDavid du Colombier break;
250959cc4ca5SDavid du Colombier default: /* 1, 2, 4, 8, 16, 32 */
251059cc4ca5SDavid du Colombier for(d=i->depth; d<32; d*=2)
251159cc4ca5SDavid du Colombier bits = (bits << d) | bits;
251259cc4ca5SDavid du Colombier memsetl(wordaddr(i, i->r.min), bits, i->width*Dy(i->r));
251359cc4ca5SDavid du Colombier break;
251459cc4ca5SDavid du Colombier }
251559cc4ca5SDavid du Colombier }
251659cc4ca5SDavid du Colombier
2517