1*8ccd4a63SDavid du Colombier #include <u.h> 2*8ccd4a63SDavid du Colombier #include <libc.h> 3*8ccd4a63SDavid du Colombier #include <draw.h> 4*8ccd4a63SDavid du Colombier #include <memdraw.h> 57dd7cddfSDavid du Colombier 6*8ccd4a63SDavid du Colombier int drawdebug; 7*8ccd4a63SDavid du Colombier static int tablesbuilt; 87dd7cddfSDavid du Colombier 97dd7cddfSDavid du Colombier /* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */ 107dd7cddfSDavid du Colombier #define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19) 117dd7cddfSDavid du Colombier 127dd7cddfSDavid du Colombier /* 137dd7cddfSDavid du Colombier * for 0 ≤ x ≤ 255*255, (x*0x0101+0x100)>>16 is a perfect approximation. 147dd7cddfSDavid du Colombier * for 0 ≤ x < (1<<16), x/255 = ((x+1)*0x0101)>>16 is a perfect approximation. 157dd7cddfSDavid du Colombier * the last one is perfect for all up to 1<<16, avoids a multiply, but requires a rathole. 167dd7cddfSDavid du Colombier */ 177dd7cddfSDavid du Colombier /* #define DIV255(x) (((x)*257+256)>>16) */ 187dd7cddfSDavid du Colombier #define DIV255(x) ((((x)+1)*257)>>16) 197dd7cddfSDavid du Colombier /* #define DIV255(x) (tmp=(x)+1, (tmp+(tmp>>8))>>8) */ 207dd7cddfSDavid du Colombier 21*8ccd4a63SDavid du Colombier #define MUL(x, y, t) (t = (x)*(y)+128, (t+(t>>8))>>8) 22*8ccd4a63SDavid du Colombier #define MASK13 0xFF00FF00 23*8ccd4a63SDavid du Colombier #define MASK02 0x00FF00FF 24*8ccd4a63SDavid du Colombier #define MUL13(a, x, t) (t = (a)*(((x)&MASK13)>>8)+128, ((t+((t>>8)&MASK02))>>8)&MASK02) 25*8ccd4a63SDavid du Colombier #define MUL02(a, x, t) (t = (a)*(((x)&MASK02)>>0)+128, ((t+((t>>8)&MASK02))>>8)&MASK02) 26*8ccd4a63SDavid du Colombier #define MUL0123(a, x, s, t) ((MUL13(a, x, s)<<8)|MUL02(a, x, t)) 27*8ccd4a63SDavid du Colombier 28*8ccd4a63SDavid du Colombier #define MUL2(u, v, x, y) (t = (u)*(v)+(x)*(y)+256, (t+(t>>8))>>8) 29*8ccd4a63SDavid du Colombier 307dd7cddfSDavid du Colombier static void mktables(void); 317dd7cddfSDavid du Colombier typedef int Subdraw(Memdrawparam*); 327dd7cddfSDavid du Colombier static Subdraw chardraw, alphadraw, memoptdraw; 337dd7cddfSDavid du Colombier 347dd7cddfSDavid du Colombier static Memimage* memones; 357dd7cddfSDavid du Colombier static Memimage* memzeros; 367dd7cddfSDavid du Colombier Memimage *memwhite; 377dd7cddfSDavid du Colombier Memimage *memblack; 387dd7cddfSDavid du Colombier Memimage *memtransparent; 397dd7cddfSDavid du Colombier Memimage *memopaque; 407dd7cddfSDavid du Colombier 41*8ccd4a63SDavid du Colombier int _ifmt(Fmt*); 427dd7cddfSDavid du Colombier 437dd7cddfSDavid du Colombier void 447dd7cddfSDavid du Colombier _memimageinit(void) 457dd7cddfSDavid du Colombier { 467dd7cddfSDavid du Colombier static int didinit = 0; 477dd7cddfSDavid du Colombier 487dd7cddfSDavid du Colombier if(didinit) 497dd7cddfSDavid du Colombier return; 507dd7cddfSDavid du Colombier 517dd7cddfSDavid du Colombier didinit = 1; 527dd7cddfSDavid du Colombier 537dd7cddfSDavid du Colombier mktables(); 54*8ccd4a63SDavid du Colombier _memmkcmap(); 55*8ccd4a63SDavid du Colombier 56*8ccd4a63SDavid du Colombier fmtinstall('R', Rfmt); 57*8ccd4a63SDavid du Colombier fmtinstall('P', Pfmt); 58*8ccd4a63SDavid du Colombier fmtinstall('b', _ifmt); 597dd7cddfSDavid du Colombier 607dd7cddfSDavid du Colombier memones = allocmemimage(Rect(0,0,1,1), GREY1); 617dd7cddfSDavid du Colombier memones->flags |= Frepl; 627dd7cddfSDavid du Colombier memones->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); 637dd7cddfSDavid du Colombier *byteaddr(memones, ZP) = ~0; 647dd7cddfSDavid du Colombier 657dd7cddfSDavid du Colombier memzeros = allocmemimage(Rect(0,0,1,1), GREY1); 667dd7cddfSDavid du Colombier memzeros->flags |= Frepl; 677dd7cddfSDavid du Colombier memzeros->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); 687dd7cddfSDavid du Colombier *byteaddr(memzeros, ZP) = 0; 697dd7cddfSDavid du Colombier 707dd7cddfSDavid du Colombier if(memones == nil || memzeros == nil) 717dd7cddfSDavid du Colombier assert(0 /*cannot initialize memimage library */); /* RSC BUG */ 727dd7cddfSDavid du Colombier 737dd7cddfSDavid du Colombier memwhite = memones; 747dd7cddfSDavid du Colombier memblack = memzeros; 757dd7cddfSDavid du Colombier memopaque = memones; 767dd7cddfSDavid du Colombier memtransparent = memzeros; 777dd7cddfSDavid du Colombier } 787dd7cddfSDavid du Colombier 79*8ccd4a63SDavid du Colombier ulong _imgtorgba(Memimage*, ulong); 80*8ccd4a63SDavid du Colombier ulong _rgbatoimg(Memimage*, ulong); 81*8ccd4a63SDavid du Colombier ulong _pixelbits(Memimage*, Point); 827dd7cddfSDavid du Colombier 837dd7cddfSDavid du Colombier #define DBG if(0) 84*8ccd4a63SDavid du Colombier static Memdrawparam par; 85*8ccd4a63SDavid du Colombier 867dd7cddfSDavid du Colombier Memdrawparam* 87*8ccd4a63SDavid du Colombier _memimagedrawsetup(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op) 887dd7cddfSDavid du Colombier { 897dd7cddfSDavid du Colombier 907dd7cddfSDavid du Colombier if(mask == nil) 917dd7cddfSDavid du Colombier mask = memopaque; 927dd7cddfSDavid du Colombier 93*8ccd4a63SDavid 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); 947dd7cddfSDavid du Colombier 957dd7cddfSDavid du Colombier if(drawclip(dst, &r, src, &p0, mask, &p1, &par.sr, &par.mr) == 0){ 96*8ccd4a63SDavid du Colombier // if(drawdebug) 97*8ccd4a63SDavid du Colombier // iprint("empty clipped rectangle\n"); 987dd7cddfSDavid du Colombier return nil; 997dd7cddfSDavid du Colombier } 1007dd7cddfSDavid du Colombier 101*8ccd4a63SDavid du Colombier if(op < Clear || op > SoverD){ 102*8ccd4a63SDavid du Colombier // if(drawdebug) 103*8ccd4a63SDavid du Colombier // iprint("op out of range: %d\n", op); 104*8ccd4a63SDavid du Colombier return nil; 105*8ccd4a63SDavid du Colombier } 106*8ccd4a63SDavid du Colombier 107*8ccd4a63SDavid du Colombier par.op = op; 1087dd7cddfSDavid du Colombier par.dst = dst; 1097dd7cddfSDavid du Colombier par.r = r; 1107dd7cddfSDavid du Colombier par.src = src; 1117dd7cddfSDavid du Colombier /* par.sr set by drawclip */ 1127dd7cddfSDavid du Colombier par.mask = mask; 1137dd7cddfSDavid du Colombier /* par.mr set by drawclip */ 1147dd7cddfSDavid du Colombier 1157dd7cddfSDavid du Colombier par.state = 0; 1167dd7cddfSDavid du Colombier if(src->flags&Frepl){ 1177dd7cddfSDavid du Colombier par.state |= Replsrc; 1187dd7cddfSDavid du Colombier if(Dx(src->r)==1 && Dy(src->r)==1){ 119*8ccd4a63SDavid du Colombier par.sval = _pixelbits(src, src->r.min); 1207dd7cddfSDavid du Colombier par.state |= Simplesrc; 1217dd7cddfSDavid du Colombier par.srgba = _imgtorgba(src, par.sval); 1227dd7cddfSDavid du Colombier par.sdval = _rgbatoimg(dst, par.srgba); 123*8ccd4a63SDavid du Colombier if((par.srgba&0xFF) == 0 && (op&DoutS)){ 124*8ccd4a63SDavid du Colombier // if (drawdebug) iprint("fill with transparent source\n"); 125*8ccd4a63SDavid du Colombier return nil; /* no-op successfully handled */ 126*8ccd4a63SDavid du Colombier } 1277dd7cddfSDavid du Colombier } 1287dd7cddfSDavid du Colombier } 1297dd7cddfSDavid du Colombier 1307dd7cddfSDavid du Colombier if(mask->flags & Frepl){ 1317dd7cddfSDavid du Colombier par.state |= Replmask; 1327dd7cddfSDavid du Colombier if(Dx(mask->r)==1 && Dy(mask->r)==1){ 133*8ccd4a63SDavid du Colombier par.mval = _pixelbits(mask, mask->r.min); 134*8ccd4a63SDavid du Colombier if(par.mval == 0 && (op&DoutS)){ 135*8ccd4a63SDavid du Colombier // if(drawdebug) iprint("fill with zero mask\n"); 1367dd7cddfSDavid du Colombier return nil; /* no-op successfully handled */ 1377dd7cddfSDavid du Colombier } 1387dd7cddfSDavid du Colombier par.state |= Simplemask; 1397dd7cddfSDavid du Colombier if(par.mval == ~0) 1407dd7cddfSDavid du Colombier par.state |= Fullmask; 1417dd7cddfSDavid du Colombier par.mrgba = _imgtorgba(mask, par.mval); 1427dd7cddfSDavid du Colombier } 1437dd7cddfSDavid du Colombier } 1447dd7cddfSDavid du Colombier 145*8ccd4a63SDavid du Colombier // if(drawdebug) 146*8ccd4a63SDavid du Colombier // iprint("dr %R sr %R mr %R...", r, par.sr, par.mr); 147*8ccd4a63SDavid du Colombier DBG print("draw dr %R sr %R mr %R %lux\n", r, par.sr, par.mr, par.state); 1487dd7cddfSDavid du Colombier 1497dd7cddfSDavid du Colombier return ∥ 1507dd7cddfSDavid du Colombier } 1517dd7cddfSDavid du Colombier 1527dd7cddfSDavid du Colombier void 1537dd7cddfSDavid du Colombier _memimagedraw(Memdrawparam *par) 1547dd7cddfSDavid du Colombier { 1557dd7cddfSDavid du Colombier if (par == nil) 1567dd7cddfSDavid du Colombier return; 1577dd7cddfSDavid du Colombier 1587dd7cddfSDavid du Colombier /* 1597dd7cddfSDavid du Colombier * Now that we've clipped the parameters down to be consistent, we 1607dd7cddfSDavid du Colombier * simply try sub-drawing routines in order until we find one that was able 1617dd7cddfSDavid du Colombier * to handle us. If the sub-drawing routine returns zero, it means it was 1627dd7cddfSDavid du Colombier * unable to satisfy the request, so we do not return. 1637dd7cddfSDavid du Colombier */ 1647dd7cddfSDavid du Colombier 1657dd7cddfSDavid du Colombier /* 1667dd7cddfSDavid du Colombier * Hardware support. Each video driver provides this function, 1677dd7cddfSDavid du Colombier * which checks to see if there is anything it can help with. 1687dd7cddfSDavid du Colombier * There could be an if around this checking to see if dst is in video memory. 1697dd7cddfSDavid du Colombier */ 170*8ccd4a63SDavid du Colombier DBG print("test hwdraw\n"); 171*8ccd4a63SDavid du Colombier if(hwdraw(par)){ 172*8ccd4a63SDavid du Colombier //if(drawdebug) iprint("hw handled\n"); 173*8ccd4a63SDavid du Colombier DBG print("hwdraw handled\n"); 1747dd7cddfSDavid du Colombier return; 1757dd7cddfSDavid du Colombier } 1767dd7cddfSDavid du Colombier /* 1777dd7cddfSDavid du Colombier * Optimizations using memmove and memset. 1787dd7cddfSDavid du Colombier */ 179*8ccd4a63SDavid du Colombier DBG print("test memoptdraw\n"); 1807dd7cddfSDavid du Colombier if(memoptdraw(par)){ 181*8ccd4a63SDavid du Colombier //if(drawdebug) iprint("memopt handled\n"); 182*8ccd4a63SDavid du Colombier DBG print("memopt handled\n"); 1837dd7cddfSDavid du Colombier return; 1847dd7cddfSDavid du Colombier } 1857dd7cddfSDavid du Colombier 1867dd7cddfSDavid du Colombier /* 1877dd7cddfSDavid du Colombier * Character drawing. 1887dd7cddfSDavid du Colombier * Solid source color being painted through a boolean mask onto a high res image. 1897dd7cddfSDavid du Colombier */ 190*8ccd4a63SDavid du Colombier DBG print("test chardraw\n"); 1917dd7cddfSDavid du Colombier if(chardraw(par)){ 192*8ccd4a63SDavid du Colombier //if(drawdebug) iprint("chardraw handled\n"); 193*8ccd4a63SDavid du Colombier DBG print("chardraw handled\n"); 1947dd7cddfSDavid du Colombier return; 1957dd7cddfSDavid du Colombier } 1967dd7cddfSDavid du Colombier 1977dd7cddfSDavid du Colombier /* 1987dd7cddfSDavid du Colombier * General calculation-laden case that does alpha for each pixel. 1997dd7cddfSDavid du Colombier */ 200*8ccd4a63SDavid du Colombier DBG print("do alphadraw\n"); 2017dd7cddfSDavid du Colombier alphadraw(par); 202*8ccd4a63SDavid du Colombier //if(drawdebug) iprint("alphadraw handled\n"); 203*8ccd4a63SDavid du Colombier DBG print("alphadraw handled\n"); 2047dd7cddfSDavid du Colombier } 2057dd7cddfSDavid du Colombier #undef DBG 2067dd7cddfSDavid du Colombier 2077dd7cddfSDavid du Colombier /* 2087dd7cddfSDavid du Colombier * Clip the destination rectangle further based on the properties of the 2097dd7cddfSDavid du Colombier * source and mask rectangles. Once the destination rectangle is properly 2107dd7cddfSDavid du Colombier * clipped, adjust the source and mask rectangles to be the same size. 2117dd7cddfSDavid du Colombier * Then if source or mask is replicated, move its clipped rectangle 2127dd7cddfSDavid du Colombier * so that its minimum point falls within the repl rectangle. 2137dd7cddfSDavid du Colombier * 2147dd7cddfSDavid du Colombier * Return zero if the final rectangle is null. 2157dd7cddfSDavid du Colombier */ 2167dd7cddfSDavid du Colombier int 2177dd7cddfSDavid du Colombier drawclip(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask, Point *p1, Rectangle *sr, Rectangle *mr) 2187dd7cddfSDavid du Colombier { 2197dd7cddfSDavid du Colombier Point rmin, delta; 2207dd7cddfSDavid du Colombier int splitcoords; 2217dd7cddfSDavid du Colombier Rectangle omr; 2227dd7cddfSDavid du Colombier 2237dd7cddfSDavid du Colombier if(r->min.x>=r->max.x || r->min.y>=r->max.y) 2247dd7cddfSDavid du Colombier return 0; 2257dd7cddfSDavid du Colombier splitcoords = (p0->x!=p1->x) || (p0->y!=p1->y); 2267dd7cddfSDavid du Colombier /* clip to destination */ 2277dd7cddfSDavid du Colombier rmin = r->min; 2287dd7cddfSDavid du Colombier if(!rectclip(r, dst->r) || !rectclip(r, dst->clipr)) 2297dd7cddfSDavid du Colombier return 0; 2307dd7cddfSDavid du Colombier /* move mask point */ 2317dd7cddfSDavid du Colombier p1->x += r->min.x-rmin.x; 2327dd7cddfSDavid du Colombier p1->y += r->min.y-rmin.y; 2337dd7cddfSDavid du Colombier /* move source point */ 2347dd7cddfSDavid du Colombier p0->x += r->min.x-rmin.x; 2357dd7cddfSDavid du Colombier p0->y += r->min.y-rmin.y; 2367dd7cddfSDavid du Colombier /* map destination rectangle into source */ 2377dd7cddfSDavid du Colombier sr->min = *p0; 2387dd7cddfSDavid du Colombier sr->max.x = p0->x+Dx(*r); 2397dd7cddfSDavid du Colombier sr->max.y = p0->y+Dy(*r); 2407dd7cddfSDavid du Colombier /* sr is r in source coordinates; clip to source */ 2417dd7cddfSDavid du Colombier if(!(src->flags&Frepl) && !rectclip(sr, src->r)) 2427dd7cddfSDavid du Colombier return 0; 2437dd7cddfSDavid du Colombier if(!rectclip(sr, src->clipr)) 2447dd7cddfSDavid du Colombier return 0; 2457dd7cddfSDavid du Colombier /* compute and clip rectangle in mask */ 2467dd7cddfSDavid du Colombier if(splitcoords){ 2477dd7cddfSDavid du Colombier /* move mask point with source */ 2487dd7cddfSDavid du Colombier p1->x += sr->min.x-p0->x; 2497dd7cddfSDavid du Colombier p1->y += sr->min.y-p0->y; 2507dd7cddfSDavid du Colombier mr->min = *p1; 2517dd7cddfSDavid du Colombier mr->max.x = p1->x+Dx(*sr); 2527dd7cddfSDavid du Colombier mr->max.y = p1->y+Dy(*sr); 2537dd7cddfSDavid du Colombier omr = *mr; 2547dd7cddfSDavid du Colombier /* mr is now rectangle in mask; clip it */ 2557dd7cddfSDavid du Colombier if(!(mask->flags&Frepl) && !rectclip(mr, mask->r)) 2567dd7cddfSDavid du Colombier return 0; 2577dd7cddfSDavid du Colombier if(!rectclip(mr, mask->clipr)) 2587dd7cddfSDavid du Colombier return 0; 2597dd7cddfSDavid du Colombier /* reflect any clips back to source */ 2607dd7cddfSDavid du Colombier sr->min.x += mr->min.x-omr.min.x; 2617dd7cddfSDavid du Colombier sr->min.y += mr->min.y-omr.min.y; 2627dd7cddfSDavid du Colombier sr->max.x += mr->max.x-omr.max.x; 2637dd7cddfSDavid du Colombier sr->max.y += mr->max.y-omr.max.y; 2647dd7cddfSDavid du Colombier *p1 = mr->min; 2657dd7cddfSDavid du Colombier }else{ 2667dd7cddfSDavid du Colombier if(!(mask->flags&Frepl) && !rectclip(sr, mask->r)) 2677dd7cddfSDavid du Colombier return 0; 2687dd7cddfSDavid du Colombier if(!rectclip(sr, mask->clipr)) 2697dd7cddfSDavid du Colombier return 0; 2707dd7cddfSDavid du Colombier *p1 = sr->min; 2717dd7cddfSDavid du Colombier } 2727dd7cddfSDavid du Colombier 2737dd7cddfSDavid du Colombier /* move source clipping back to destination */ 2747dd7cddfSDavid du Colombier delta.x = r->min.x - p0->x; 2757dd7cddfSDavid du Colombier delta.y = r->min.y - p0->y; 2767dd7cddfSDavid du Colombier r->min.x = sr->min.x + delta.x; 2777dd7cddfSDavid du Colombier r->min.y = sr->min.y + delta.y; 2787dd7cddfSDavid du Colombier r->max.x = sr->max.x + delta.x; 2797dd7cddfSDavid du Colombier r->max.y = sr->max.y + delta.y; 2807dd7cddfSDavid du Colombier 2817dd7cddfSDavid du Colombier /* move source rectangle so sr->min is in src->r */ 2827dd7cddfSDavid du Colombier if(src->flags&Frepl) { 2837dd7cddfSDavid du Colombier delta.x = drawreplxy(src->r.min.x, src->r.max.x, sr->min.x) - sr->min.x; 2847dd7cddfSDavid du Colombier delta.y = drawreplxy(src->r.min.y, src->r.max.y, sr->min.y) - sr->min.y; 2857dd7cddfSDavid du Colombier sr->min.x += delta.x; 2867dd7cddfSDavid du Colombier sr->min.y += delta.y; 2877dd7cddfSDavid du Colombier sr->max.x += delta.x; 2887dd7cddfSDavid du Colombier sr->max.y += delta.y; 2897dd7cddfSDavid du Colombier } 2907dd7cddfSDavid du Colombier *p0 = sr->min; 2917dd7cddfSDavid du Colombier 2927dd7cddfSDavid du Colombier /* move mask point so it is in mask->r */ 293*8ccd4a63SDavid du Colombier *p1 = drawrepl(mask->r, *p1); 2947dd7cddfSDavid du Colombier mr->min = *p1; 2957dd7cddfSDavid du Colombier mr->max.x = p1->x+Dx(*sr); 2967dd7cddfSDavid du Colombier mr->max.y = p1->y+Dy(*sr); 2977dd7cddfSDavid du Colombier 2987dd7cddfSDavid du Colombier assert(Dx(*sr) == Dx(*mr) && Dx(*mr) == Dx(*r)); 2997dd7cddfSDavid du Colombier assert(Dy(*sr) == Dy(*mr) && Dy(*mr) == Dy(*r)); 300*8ccd4a63SDavid du Colombier assert(ptinrect(*p0, src->r)); 301*8ccd4a63SDavid du Colombier assert(ptinrect(*p1, mask->r)); 302*8ccd4a63SDavid du Colombier assert(ptinrect(r->min, dst->r)); 3037dd7cddfSDavid du Colombier 3047dd7cddfSDavid du Colombier return 1; 3057dd7cddfSDavid du Colombier } 3067dd7cddfSDavid du Colombier 3077dd7cddfSDavid du Colombier /* 3087dd7cddfSDavid du Colombier * Conversion tables. 3097dd7cddfSDavid du Colombier */ 3107dd7cddfSDavid du Colombier static uchar replbit[1+8][256]; /* replbit[x][y] is the replication of the x-bit quantity y to 8-bit depth */ 3117dd7cddfSDavid du Colombier 3127dd7cddfSDavid du Colombier /* 3137dd7cddfSDavid du Colombier * bitmap of how to replicate n bits to fill 8, for 1 ≤ n ≤ 8. 3147dd7cddfSDavid du Colombier * the X's are where to put the bottom (ones) bit of the n-bit pattern. 3157dd7cddfSDavid du Colombier * only the top 8 bits of the result are actually used. 3167dd7cddfSDavid du Colombier * (the lower 8 bits are needed to get bits in the right place 3177dd7cddfSDavid du Colombier * when n is not a divisor of 8.) 3187dd7cddfSDavid du Colombier * 3197dd7cddfSDavid du Colombier * Should check to see if its easier to just refer to replmul than 3207dd7cddfSDavid du Colombier * use the precomputed values in replbit. On PCs it may well 3217dd7cddfSDavid du Colombier * be; on machines with slow multiply instructions it probably isn't. 3227dd7cddfSDavid du Colombier */ 3237dd7cddfSDavid du Colombier #define a ((((((((((((((((0 3247dd7cddfSDavid du Colombier #define X *2+1) 3257dd7cddfSDavid du Colombier #define _ *2) 3267dd7cddfSDavid du Colombier static int replmul[1+8] = { 3277dd7cddfSDavid du Colombier 0, 3287dd7cddfSDavid du Colombier a X X X X X X X X X X X X X X X X, 3297dd7cddfSDavid du Colombier a _ X _ X _ X _ X _ X _ X _ X _ X, 3307dd7cddfSDavid du Colombier a _ _ X _ _ X _ _ X _ _ X _ _ X _, 3317dd7cddfSDavid du Colombier a _ _ _ X _ _ _ X _ _ _ X _ _ _ X, 3327dd7cddfSDavid du Colombier a _ _ _ _ X _ _ _ _ X _ _ _ _ X _, 3337dd7cddfSDavid du Colombier a _ _ _ _ _ X _ _ _ _ _ X _ _ _ _, 3347dd7cddfSDavid du Colombier a _ _ _ _ _ _ X _ _ _ _ _ _ X _ _, 3357dd7cddfSDavid du Colombier a _ _ _ _ _ _ _ X _ _ _ _ _ _ _ X, 3367dd7cddfSDavid du Colombier }; 3377dd7cddfSDavid du Colombier #undef a 3387dd7cddfSDavid du Colombier #undef X 3397dd7cddfSDavid du Colombier #undef _ 3407dd7cddfSDavid du Colombier 3417dd7cddfSDavid du Colombier static void 3427dd7cddfSDavid du Colombier mktables(void) 3437dd7cddfSDavid du Colombier { 344*8ccd4a63SDavid du Colombier int i, j, small; 3457dd7cddfSDavid du Colombier 3467dd7cddfSDavid du Colombier if(tablesbuilt) 3477dd7cddfSDavid du Colombier return; 3487dd7cddfSDavid du Colombier 349*8ccd4a63SDavid du Colombier fmtinstall('R', Rfmt); 350*8ccd4a63SDavid du Colombier fmtinstall('P', Pfmt); 3517dd7cddfSDavid du Colombier tablesbuilt = 1; 352*8ccd4a63SDavid du Colombier 3537dd7cddfSDavid du Colombier /* bit replication up to 8 bits */ 3547dd7cddfSDavid du Colombier for(i=0; i<256; i++){ 3557dd7cddfSDavid du Colombier for(j=0; j<=8; j++){ /* j <= 8 [sic] */ 3567dd7cddfSDavid du Colombier small = i & ((1<<j)-1); 3577dd7cddfSDavid du Colombier replbit[j][i] = (small*replmul[j])>>8; 3587dd7cddfSDavid du Colombier } 3597dd7cddfSDavid du Colombier } 3607dd7cddfSDavid du Colombier 3617dd7cddfSDavid du Colombier } 362*8ccd4a63SDavid du Colombier 363*8ccd4a63SDavid du Colombier static uchar ones = 0xff; 3647dd7cddfSDavid du Colombier 3657dd7cddfSDavid du Colombier /* 3667dd7cddfSDavid du Colombier * General alpha drawing case. Can handle anything. 3677dd7cddfSDavid du Colombier */ 3687dd7cddfSDavid du Colombier typedef struct Buffer Buffer; 3697dd7cddfSDavid du Colombier struct Buffer { 370*8ccd4a63SDavid du Colombier /* used by most routines */ 3717dd7cddfSDavid du Colombier uchar *red; 3727dd7cddfSDavid du Colombier uchar *grn; 3737dd7cddfSDavid du Colombier uchar *blu; 3747dd7cddfSDavid du Colombier uchar *alpha; 3757dd7cddfSDavid du Colombier uchar *grey; 376*8ccd4a63SDavid du Colombier ulong *rgba; 3777dd7cddfSDavid du Colombier int delta; /* number of bytes to add to pointer to get next pixel to the right */ 378*8ccd4a63SDavid du Colombier 379*8ccd4a63SDavid du Colombier /* used by boolcalc* for mask data */ 3807dd7cddfSDavid du Colombier uchar *m; /* ptr to mask data r.min byte; like p->bytermin */ 3817dd7cddfSDavid du Colombier int mskip; /* no. of left bits to skip in *m */ 3827dd7cddfSDavid du Colombier uchar *bm; /* ptr to mask data img->r.min byte; like p->bytey0s */ 3837dd7cddfSDavid du Colombier int bmskip; /* no. of left bits to skip in *bm */ 3847dd7cddfSDavid du Colombier uchar *em; /* ptr to mask data img->r.max.x byte; like p->bytey0e */ 3857dd7cddfSDavid du Colombier int emskip; /* no. of right bits to skip in *em */ 3867dd7cddfSDavid du Colombier }; 3877dd7cddfSDavid du Colombier 3887dd7cddfSDavid du Colombier typedef struct Param Param; 389*8ccd4a63SDavid du Colombier typedef Buffer Readfn(Param*, uchar*, int); 390*8ccd4a63SDavid du Colombier typedef void Writefn(Param*, uchar*, Buffer); 391*8ccd4a63SDavid du Colombier typedef Buffer Calcfn(Buffer, Buffer, Buffer, int, int, int); 3927dd7cddfSDavid du Colombier 3937dd7cddfSDavid du Colombier enum { 3947dd7cddfSDavid du Colombier MAXBCACHE = 16 3957dd7cddfSDavid du Colombier }; 3967dd7cddfSDavid du Colombier 3977dd7cddfSDavid du Colombier /* giant rathole to customize functions with */ 3987dd7cddfSDavid du Colombier struct Param { 3997dd7cddfSDavid du Colombier Readfn *replcall; 4007dd7cddfSDavid du Colombier Readfn *greymaskcall; 4017dd7cddfSDavid du Colombier Readfn *convreadcall; 4027dd7cddfSDavid du Colombier Writefn *convwritecall; 4037dd7cddfSDavid du Colombier 4047dd7cddfSDavid du Colombier Memimage *img; 4057dd7cddfSDavid du Colombier Rectangle r; 4067dd7cddfSDavid du Colombier int dx; /* of r */ 4077dd7cddfSDavid du Colombier int needbuf; 4087dd7cddfSDavid du Colombier int convgrey; 4097dd7cddfSDavid du Colombier int alphaonly; 4107dd7cddfSDavid du Colombier 4117dd7cddfSDavid du Colombier uchar *bytey0s; /* byteaddr(Pt(img->r.min.x, img->r.min.y)) */ 4127dd7cddfSDavid du Colombier uchar *bytermin; /* byteaddr(Pt(r.min.x, img->r.min.y)) */ 4137dd7cddfSDavid du Colombier uchar *bytey0e; /* byteaddr(Pt(img->r.max.x, img->r.min.y)) */ 4147dd7cddfSDavid du Colombier int bwidth; 4157dd7cddfSDavid du Colombier 4167dd7cddfSDavid du Colombier int replcache; /* if set, cache buffers */ 4177dd7cddfSDavid du Colombier Buffer bcache[MAXBCACHE]; 4187dd7cddfSDavid du Colombier ulong bfilled; 4197dd7cddfSDavid du Colombier uchar *bufbase; 4207dd7cddfSDavid du Colombier int bufoff; 4217dd7cddfSDavid du Colombier int bufdelta; 4227dd7cddfSDavid du Colombier 4237dd7cddfSDavid du Colombier int dir; 4247dd7cddfSDavid du Colombier 4257dd7cddfSDavid du Colombier int convbufoff; 4267dd7cddfSDavid du Colombier uchar *convbuf; 4277dd7cddfSDavid du Colombier Param *convdpar; 4287dd7cddfSDavid du Colombier int convdx; 4297dd7cddfSDavid du Colombier }; 4307dd7cddfSDavid du Colombier 4317dd7cddfSDavid du Colombier static uchar *drawbuf; 4327dd7cddfSDavid du Colombier static int ndrawbuf; 4337dd7cddfSDavid du Colombier static int mdrawbuf; 4347dd7cddfSDavid du Colombier static Param spar, mpar, dpar; /* easier on the stacks */ 4357dd7cddfSDavid du Colombier static Readfn greymaskread, replread, readptr; 4367dd7cddfSDavid du Colombier static Writefn nullwrite; 437*8ccd4a63SDavid du Colombier static Calcfn alphacalc0, alphacalc14, alphacalc2810, alphacalc3679, alphacalc5, alphacalc11, alphacalcS; 438*8ccd4a63SDavid du Colombier static Calcfn boolcalc14, boolcalc236789, boolcalc1011; 4397dd7cddfSDavid du Colombier 4407dd7cddfSDavid du Colombier static Readfn* readfn(Memimage*); 4417dd7cddfSDavid du Colombier static Readfn* readalphafn(Memimage*); 4427dd7cddfSDavid du Colombier static Writefn* writefn(Memimage*); 4437dd7cddfSDavid du Colombier 4447dd7cddfSDavid du Colombier static Calcfn* boolcopyfn(Memimage*, Memimage*); 445*8ccd4a63SDavid du Colombier static Readfn* convfn(Memimage*, Param*, Memimage*, Param*); 446*8ccd4a63SDavid du Colombier 447*8ccd4a63SDavid du Colombier static Calcfn *alphacalc[Ncomp] = 448*8ccd4a63SDavid du Colombier { 449*8ccd4a63SDavid du Colombier alphacalc0, /* Clear */ 450*8ccd4a63SDavid du Colombier alphacalc14, /* DoutS */ 451*8ccd4a63SDavid du Colombier alphacalc2810, /* SoutD */ 452*8ccd4a63SDavid du Colombier alphacalc3679, /* DxorS */ 453*8ccd4a63SDavid du Colombier alphacalc14, /* DinS */ 454*8ccd4a63SDavid du Colombier alphacalc5, /* D */ 455*8ccd4a63SDavid du Colombier alphacalc3679, /* DatopS */ 456*8ccd4a63SDavid du Colombier alphacalc3679, /* DoverS */ 457*8ccd4a63SDavid du Colombier alphacalc2810, /* SinD */ 458*8ccd4a63SDavid du Colombier alphacalc3679, /* SatopD */ 459*8ccd4a63SDavid du Colombier alphacalc2810, /* S */ 460*8ccd4a63SDavid du Colombier alphacalc11, /* SoverD */ 461*8ccd4a63SDavid du Colombier }; 462*8ccd4a63SDavid du Colombier 463*8ccd4a63SDavid du Colombier static Calcfn *boolcalc[Ncomp] = 464*8ccd4a63SDavid du Colombier { 465*8ccd4a63SDavid du Colombier alphacalc0, /* Clear */ 466*8ccd4a63SDavid du Colombier boolcalc14, /* DoutS */ 467*8ccd4a63SDavid du Colombier boolcalc236789, /* SoutD */ 468*8ccd4a63SDavid du Colombier boolcalc236789, /* DxorS */ 469*8ccd4a63SDavid du Colombier boolcalc14, /* DinS */ 470*8ccd4a63SDavid du Colombier alphacalc5, /* D */ 471*8ccd4a63SDavid du Colombier boolcalc236789, /* DatopS */ 472*8ccd4a63SDavid du Colombier boolcalc236789, /* DoverS */ 473*8ccd4a63SDavid du Colombier boolcalc236789, /* SinD */ 474*8ccd4a63SDavid du Colombier boolcalc236789, /* SatopD */ 475*8ccd4a63SDavid du Colombier boolcalc1011, /* S */ 476*8ccd4a63SDavid du Colombier boolcalc1011, /* SoverD */ 477*8ccd4a63SDavid du Colombier }; 4787dd7cddfSDavid du Colombier 4797dd7cddfSDavid du Colombier static int 4807dd7cddfSDavid du Colombier allocdrawbuf(void) 4817dd7cddfSDavid du Colombier { 4827dd7cddfSDavid du Colombier uchar *p; 4837dd7cddfSDavid du Colombier 4847dd7cddfSDavid du Colombier if(ndrawbuf > mdrawbuf){ 4857dd7cddfSDavid du Colombier p = realloc(drawbuf, ndrawbuf); 4867dd7cddfSDavid du Colombier if(p == nil){ 4877dd7cddfSDavid du Colombier werrstr("memimagedraw out of memory"); 4887dd7cddfSDavid du Colombier return -1; 4897dd7cddfSDavid du Colombier } 4907dd7cddfSDavid du Colombier drawbuf = p; 4917dd7cddfSDavid du Colombier mdrawbuf = ndrawbuf; 4927dd7cddfSDavid du Colombier } 4937dd7cddfSDavid du Colombier return 0; 4947dd7cddfSDavid du Colombier } 4957dd7cddfSDavid du Colombier 4967dd7cddfSDavid du Colombier static Param 4977dd7cddfSDavid du Colombier getparam(Memimage *img, Rectangle r, int convgrey, int needbuf) 4987dd7cddfSDavid du Colombier { 4997dd7cddfSDavid du Colombier Param p; 5007dd7cddfSDavid du Colombier int nbuf; 5017dd7cddfSDavid du Colombier 5027dd7cddfSDavid du Colombier memset(&p, 0, sizeof p); 5037dd7cddfSDavid du Colombier 5047dd7cddfSDavid du Colombier p.img = img; 5057dd7cddfSDavid du Colombier p.r = r; 5067dd7cddfSDavid du Colombier p.dx = Dx(r); 5077dd7cddfSDavid du Colombier p.needbuf = needbuf; 5087dd7cddfSDavid du Colombier p.convgrey = convgrey; 5097dd7cddfSDavid du Colombier 5107dd7cddfSDavid du Colombier assert(img->r.min.x <= r.min.x && r.min.x < img->r.max.x); 5117dd7cddfSDavid du Colombier 5127dd7cddfSDavid du Colombier p.bytey0s = byteaddr(img, Pt(img->r.min.x, img->r.min.y)); 5137dd7cddfSDavid du Colombier p.bytermin = byteaddr(img, Pt(r.min.x, img->r.min.y)); 5147dd7cddfSDavid du Colombier p.bytey0e = byteaddr(img, Pt(img->r.max.x, img->r.min.y)); 5157dd7cddfSDavid du Colombier p.bwidth = sizeof(ulong)*img->width; 5167dd7cddfSDavid du Colombier 5177dd7cddfSDavid du Colombier assert(p.bytey0s <= p.bytermin && p.bytermin <= p.bytey0e); 5187dd7cddfSDavid du Colombier 5197dd7cddfSDavid du Colombier if(p.r.min.x == p.img->r.min.x) 5207dd7cddfSDavid du Colombier assert(p.bytermin == p.bytey0s); 5217dd7cddfSDavid du Colombier 5227dd7cddfSDavid du Colombier nbuf = 1; 5237dd7cddfSDavid du Colombier if((img->flags&Frepl) && Dy(img->r) <= MAXBCACHE && Dy(img->r) < Dy(r)){ 5247dd7cddfSDavid du Colombier p.replcache = 1; 5257dd7cddfSDavid du Colombier nbuf = Dy(img->r); 5267dd7cddfSDavid du Colombier } 5277dd7cddfSDavid du Colombier p.bufdelta = 4*p.dx; 5287dd7cddfSDavid du Colombier p.bufoff = ndrawbuf; 5297dd7cddfSDavid du Colombier ndrawbuf += p.bufdelta*nbuf; 5307dd7cddfSDavid du Colombier 5317dd7cddfSDavid du Colombier return p; 5327dd7cddfSDavid du Colombier } 5337dd7cddfSDavid du Colombier 5347dd7cddfSDavid du Colombier static void 5357dd7cddfSDavid du Colombier clipy(Memimage *img, int *y) 5367dd7cddfSDavid du Colombier { 5377dd7cddfSDavid du Colombier int dy; 5387dd7cddfSDavid du Colombier 5397dd7cddfSDavid du Colombier dy = Dy(img->r); 5407dd7cddfSDavid du Colombier if(*y == dy) 5417dd7cddfSDavid du Colombier *y = 0; 5427dd7cddfSDavid du Colombier else if(*y == -1) 5437dd7cddfSDavid du Colombier *y = dy-1; 5447dd7cddfSDavid du Colombier assert(0 <= *y && *y < dy); 5457dd7cddfSDavid du Colombier } 5467dd7cddfSDavid du Colombier 5477dd7cddfSDavid du Colombier static void 5487dd7cddfSDavid du Colombier dumpbuf(char *s, Buffer b, int n) 5497dd7cddfSDavid du Colombier { 5507dd7cddfSDavid du Colombier int i; 5517dd7cddfSDavid du Colombier uchar *p; 5527dd7cddfSDavid du Colombier 5537dd7cddfSDavid du Colombier print("%s", s); 5547dd7cddfSDavid du Colombier for(i=0; i<n; i++){ 5557dd7cddfSDavid du Colombier print(" "); 556*8ccd4a63SDavid du Colombier if((p=b.grey)){ 5577dd7cddfSDavid du Colombier print(" k%.2uX", *p); 5587dd7cddfSDavid du Colombier b.grey += b.delta; 5597dd7cddfSDavid du Colombier }else{ 560*8ccd4a63SDavid du Colombier if((p=b.red)){ 5617dd7cddfSDavid du Colombier print(" r%.2uX", *p); 5627dd7cddfSDavid du Colombier b.red += b.delta; 5637dd7cddfSDavid du Colombier } 564*8ccd4a63SDavid du Colombier if((p=b.grn)){ 5657dd7cddfSDavid du Colombier print(" g%.2uX", *p); 5667dd7cddfSDavid du Colombier b.grn += b.delta; 5677dd7cddfSDavid du Colombier } 568*8ccd4a63SDavid du Colombier if((p=b.blu)){ 5697dd7cddfSDavid du Colombier print(" b%.2uX", *p); 5707dd7cddfSDavid du Colombier b.blu += b.delta; 5717dd7cddfSDavid du Colombier } 5727dd7cddfSDavid du Colombier } 573*8ccd4a63SDavid du Colombier if((p=b.alpha) != &ones){ 5747dd7cddfSDavid du Colombier print(" α%.2uX", *p); 5757dd7cddfSDavid du Colombier b.alpha += b.delta; 5767dd7cddfSDavid du Colombier } 5777dd7cddfSDavid du Colombier } 5787dd7cddfSDavid du Colombier print("\n"); 5797dd7cddfSDavid du Colombier } 5807dd7cddfSDavid du Colombier 5817dd7cddfSDavid du Colombier /* 5827dd7cddfSDavid du Colombier * For each scan line, we expand the pixels from source, mask, and destination 5837dd7cddfSDavid du Colombier * into byte-aligned red, green, blue, alpha, and grey channels. If buffering is not 5847dd7cddfSDavid du Colombier * needed and the channels were already byte-aligned (grey8, rgb24, rgba32, rgb32), 5857dd7cddfSDavid du Colombier * the readers need not copy the data: they can simply return pointers to the data. 5867dd7cddfSDavid du Colombier * If the destination image is grey and the source is not, it is converted using the NTSC 5877dd7cddfSDavid du Colombier * formula. 5887dd7cddfSDavid du Colombier * 5897dd7cddfSDavid du Colombier * Once we have all the channels, we call either rgbcalc or greycalc, depending on 5907dd7cddfSDavid du Colombier * whether the destination image is color. This is allowed to overwrite the dst buffer (perhaps 5917dd7cddfSDavid du Colombier * the actual data, perhaps a copy) with its result. It should only overwrite the dst buffer 5927dd7cddfSDavid du Colombier * with the same format (i.e. red bytes with red bytes, etc.) A new buffer is returned from 5937dd7cddfSDavid du Colombier * the calculator, and that buffer is passed to a function to write it to the destination. 5947dd7cddfSDavid du Colombier * If the buffer is already pointing at the destination, the writing function is a no-op. 5957dd7cddfSDavid du Colombier */ 5967dd7cddfSDavid du Colombier #define DBG if(0) 5977dd7cddfSDavid du Colombier static int 5987dd7cddfSDavid du Colombier alphadraw(Memdrawparam *par) 5997dd7cddfSDavid du Colombier { 600*8ccd4a63SDavid du Colombier int isgrey, starty, endy, op; 6017dd7cddfSDavid du Colombier int needbuf, dsty, srcy, masky; 6027dd7cddfSDavid du Colombier int y, dir, dx, dy; 6037dd7cddfSDavid du Colombier Buffer bsrc, bdst, bmask; 6047dd7cddfSDavid du Colombier Readfn *rdsrc, *rdmask, *rddst; 6057dd7cddfSDavid du Colombier Calcfn *calc; 6067dd7cddfSDavid du Colombier Writefn *wrdst; 6077dd7cddfSDavid du Colombier Memimage *src, *mask, *dst; 6087dd7cddfSDavid du Colombier Rectangle r, sr, mr; 6097dd7cddfSDavid du Colombier 6107dd7cddfSDavid du Colombier r = par->r; 6117dd7cddfSDavid du Colombier dx = Dx(r); 6127dd7cddfSDavid du Colombier dy = Dy(r); 6137dd7cddfSDavid du Colombier 6147dd7cddfSDavid du Colombier ndrawbuf = 0; 6157dd7cddfSDavid du Colombier 6167dd7cddfSDavid du Colombier src = par->src; 6177dd7cddfSDavid du Colombier mask = par->mask; 6187dd7cddfSDavid du Colombier dst = par->dst; 6197dd7cddfSDavid du Colombier sr = par->sr; 6207dd7cddfSDavid du Colombier mr = par->mr; 621*8ccd4a63SDavid du Colombier op = par->op; 6227dd7cddfSDavid du Colombier 6237dd7cddfSDavid du Colombier isgrey = dst->flags&Fgrey; 6247dd7cddfSDavid du Colombier 6257dd7cddfSDavid du Colombier /* 6267dd7cddfSDavid du Colombier * Buffering when src and dst are the same bitmap is sufficient but not 6277dd7cddfSDavid du Colombier * necessary. There are stronger conditions we could use. We could 6287dd7cddfSDavid du Colombier * check to see if the rectangles intersect, and if simply moving in the 6297dd7cddfSDavid du Colombier * correct y direction can avoid the need to buffer. 6307dd7cddfSDavid du Colombier */ 6317dd7cddfSDavid du Colombier needbuf = (src->data == dst->data); 6327dd7cddfSDavid du Colombier 6337dd7cddfSDavid du Colombier spar = getparam(src, sr, isgrey, needbuf); 6347dd7cddfSDavid du Colombier dpar = getparam(dst, r, isgrey, needbuf); 635*8ccd4a63SDavid du Colombier mpar = getparam(mask, mr, 0, needbuf); 6367dd7cddfSDavid du Colombier 6377dd7cddfSDavid du Colombier dir = (needbuf && byteaddr(dst, r.min) > byteaddr(src, sr.min)) ? -1 : 1; 6387dd7cddfSDavid du Colombier spar.dir = mpar.dir = dpar.dir = dir; 6397dd7cddfSDavid du Colombier 6407dd7cddfSDavid du Colombier /* 6417dd7cddfSDavid du Colombier * If the mask is purely boolean, we can convert from src to dst format 6427dd7cddfSDavid du Colombier * when we read src, and then just copy it to dst where the mask tells us to. 6437dd7cddfSDavid du Colombier * This requires a boolean (1-bit grey) mask and lack of a source alpha channel. 6447dd7cddfSDavid du Colombier * 6457dd7cddfSDavid du Colombier * The computation is accomplished by assigning the function pointers as follows: 6467dd7cddfSDavid du Colombier * rdsrc - read and convert source into dst format in a buffer 6477dd7cddfSDavid du Colombier * rdmask - convert mask to bytes, set pointer to it 6487dd7cddfSDavid du Colombier * rddst - fill with pointer to real dst data, but do no reads 6497dd7cddfSDavid du Colombier * calc - copy src onto dst when mask says to. 6507dd7cddfSDavid du Colombier * wrdst - do nothing 6517dd7cddfSDavid du Colombier * This is slightly sleazy, since things aren't doing exactly what their names say, 6527dd7cddfSDavid du Colombier * but it avoids a fair amount of code duplication to make this a case here 6537dd7cddfSDavid du Colombier * rather than have a separate booldraw. 6547dd7cddfSDavid du Colombier */ 655*8ccd4a63SDavid du Colombier //if(drawdebug) iprint("flag %lud mchan %lux=?%x dd %d\n", src->flags&Falpha, mask->chan, GREY1, dst->depth); 656*8ccd4a63SDavid du Colombier if(!(src->flags&Falpha) && mask->chan == GREY1 && dst->depth >= 8 && op == SoverD){ 657*8ccd4a63SDavid du Colombier //if(drawdebug) iprint("boolcopy..."); 6587dd7cddfSDavid du Colombier rdsrc = convfn(dst, &dpar, src, &spar); 6597dd7cddfSDavid du Colombier rddst = readptr; 6607dd7cddfSDavid du Colombier rdmask = readfn(mask); 6617dd7cddfSDavid du Colombier calc = boolcopyfn(dst, mask); 6627dd7cddfSDavid du Colombier wrdst = nullwrite; 6637dd7cddfSDavid du Colombier }else{ 6647dd7cddfSDavid du Colombier /* usual alphadraw parameter fetching */ 6657dd7cddfSDavid du Colombier rdsrc = readfn(src); 6667dd7cddfSDavid du Colombier rddst = readfn(dst); 6677dd7cddfSDavid du Colombier wrdst = writefn(dst); 668*8ccd4a63SDavid du Colombier calc = alphacalc[op]; 6697dd7cddfSDavid du Colombier 6707dd7cddfSDavid du Colombier /* 6717dd7cddfSDavid du Colombier * If there is no alpha channel, we'll ask for a grey channel 6727dd7cddfSDavid du Colombier * and pretend it is the alpha. 6737dd7cddfSDavid du Colombier */ 6747dd7cddfSDavid du Colombier if(mask->flags&Falpha){ 6757dd7cddfSDavid du Colombier rdmask = readalphafn(mask); 6767dd7cddfSDavid du Colombier mpar.alphaonly = 1; 6777dd7cddfSDavid du Colombier }else{ 6787dd7cddfSDavid du Colombier mpar.greymaskcall = readfn(mask); 6797dd7cddfSDavid du Colombier mpar.convgrey = 1; 6807dd7cddfSDavid du Colombier rdmask = greymaskread; 6817dd7cddfSDavid du Colombier 6827dd7cddfSDavid du Colombier /* 6837dd7cddfSDavid du Colombier * Should really be above, but then boolcopyfns would have 6847dd7cddfSDavid du Colombier * to deal with bit alignment, and I haven't written that. 6857dd7cddfSDavid du Colombier * 6867dd7cddfSDavid du Colombier * This is a common case for things like ellipse drawing. 6877dd7cddfSDavid du Colombier * When there's no alpha involved and the mask is boolean, 6887dd7cddfSDavid du Colombier * we can avoid all the division and multiplication. 6897dd7cddfSDavid du Colombier */ 6907dd7cddfSDavid du Colombier if(mask->chan == GREY1 && !(src->flags&Falpha)) 691*8ccd4a63SDavid du Colombier calc = boolcalc[op]; 692*8ccd4a63SDavid du Colombier else if(op == SoverD && !(src->flags&Falpha)) 693*8ccd4a63SDavid du Colombier calc = alphacalcS; 6947dd7cddfSDavid du Colombier } 6957dd7cddfSDavid du Colombier } 6967dd7cddfSDavid du Colombier 6977dd7cddfSDavid du Colombier /* 6987dd7cddfSDavid du Colombier * If the image has a small enough repl rectangle, 6997dd7cddfSDavid du Colombier * we can just read each line once and cache them. 7007dd7cddfSDavid du Colombier */ 7017dd7cddfSDavid du Colombier if(spar.replcache){ 7027dd7cddfSDavid du Colombier spar.replcall = rdsrc; 7037dd7cddfSDavid du Colombier rdsrc = replread; 7047dd7cddfSDavid du Colombier } 7057dd7cddfSDavid du Colombier if(mpar.replcache){ 7067dd7cddfSDavid du Colombier mpar.replcall = rdmask; 7077dd7cddfSDavid du Colombier rdmask = replread; 7087dd7cddfSDavid du Colombier } 7097dd7cddfSDavid du Colombier 7107dd7cddfSDavid du Colombier if(allocdrawbuf() < 0) 7117dd7cddfSDavid du Colombier return 0; 7127dd7cddfSDavid du Colombier 7137dd7cddfSDavid du Colombier /* 7147dd7cddfSDavid du Colombier * Before we were saving only offsets from drawbuf in the parameter 7157dd7cddfSDavid du Colombier * structures; now that drawbuf has been grown to accomodate us, 7167dd7cddfSDavid du Colombier * we can fill in the pointers. 7177dd7cddfSDavid du Colombier */ 7187dd7cddfSDavid du Colombier spar.bufbase = drawbuf+spar.bufoff; 7197dd7cddfSDavid du Colombier mpar.bufbase = drawbuf+mpar.bufoff; 7207dd7cddfSDavid du Colombier dpar.bufbase = drawbuf+dpar.bufoff; 7217dd7cddfSDavid du Colombier spar.convbuf = drawbuf+spar.convbufoff; 7227dd7cddfSDavid du Colombier 7237dd7cddfSDavid du Colombier if(dir == 1){ 7247dd7cddfSDavid du Colombier starty = 0; 7257dd7cddfSDavid du Colombier endy = dy; 7267dd7cddfSDavid du Colombier }else{ 7277dd7cddfSDavid du Colombier starty = dy-1; 7287dd7cddfSDavid du Colombier endy = -1; 7297dd7cddfSDavid du Colombier } 7307dd7cddfSDavid du Colombier 7317dd7cddfSDavid du Colombier /* 7327dd7cddfSDavid du Colombier * srcy, masky, and dsty are offsets from the top of their 7337dd7cddfSDavid du Colombier * respective Rectangles. they need to be contained within 7347dd7cddfSDavid du Colombier * the rectangles, so clipy can keep them there without division. 7357dd7cddfSDavid du Colombier */ 7367dd7cddfSDavid du Colombier srcy = (starty + sr.min.y - src->r.min.y)%Dy(src->r); 7377dd7cddfSDavid du Colombier masky = (starty + mr.min.y - mask->r.min.y)%Dy(mask->r); 7387dd7cddfSDavid du Colombier dsty = starty + r.min.y - dst->r.min.y; 7397dd7cddfSDavid du Colombier 7407dd7cddfSDavid du Colombier assert(0 <= srcy && srcy < Dy(src->r)); 7417dd7cddfSDavid du Colombier assert(0 <= masky && masky < Dy(mask->r)); 7427dd7cddfSDavid du Colombier assert(0 <= dsty && dsty < Dy(dst->r)); 7437dd7cddfSDavid du Colombier 7447dd7cddfSDavid du Colombier for(y=starty; y!=endy; y+=dir, srcy+=dir, masky+=dir, dsty+=dir){ 7457dd7cddfSDavid du Colombier clipy(src, &srcy); 7467dd7cddfSDavid du Colombier clipy(dst, &dsty); 7477dd7cddfSDavid du Colombier clipy(mask, &masky); 7487dd7cddfSDavid du Colombier 7497dd7cddfSDavid du Colombier bsrc = rdsrc(&spar, spar.bufbase, srcy); 7507dd7cddfSDavid du Colombier DBG print("["); 7517dd7cddfSDavid du Colombier bmask = rdmask(&mpar, mpar.bufbase, masky); 7527dd7cddfSDavid du Colombier DBG print("]\n"); 7537dd7cddfSDavid du Colombier bdst = rddst(&dpar, dpar.bufbase, dsty); 7547dd7cddfSDavid du Colombier DBG dumpbuf("src", bsrc, dx); 7557dd7cddfSDavid du Colombier DBG dumpbuf("mask", bmask, dx); 7567dd7cddfSDavid du Colombier DBG dumpbuf("dst", bdst, dx); 757*8ccd4a63SDavid du Colombier bdst = calc(bdst, bsrc, bmask, dx, isgrey, op); 7587dd7cddfSDavid du Colombier wrdst(&dpar, dpar.bytermin+dsty*dpar.bwidth, bdst); 7597dd7cddfSDavid du Colombier } 7607dd7cddfSDavid du Colombier 7617dd7cddfSDavid du Colombier return 1; 7627dd7cddfSDavid du Colombier } 7637dd7cddfSDavid du Colombier #undef DBG 7647dd7cddfSDavid du Colombier 7657dd7cddfSDavid du Colombier static Buffer 766*8ccd4a63SDavid du Colombier alphacalc0(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op) 767*8ccd4a63SDavid du Colombier { 768*8ccd4a63SDavid du Colombier USED(grey); 769*8ccd4a63SDavid du Colombier USED(op); 770*8ccd4a63SDavid du Colombier memset(bdst.rgba, 0, dx*bdst.delta); 771*8ccd4a63SDavid du Colombier return bdst; 772*8ccd4a63SDavid du Colombier } 773*8ccd4a63SDavid du Colombier 774*8ccd4a63SDavid du Colombier static Buffer 775*8ccd4a63SDavid du Colombier alphacalc14(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op) 7767dd7cddfSDavid du Colombier { 7777dd7cddfSDavid du Colombier Buffer obdst; 778*8ccd4a63SDavid du Colombier int fd, sadelta; 779*8ccd4a63SDavid du Colombier int i, sa, ma, q; 780*8ccd4a63SDavid du Colombier ulong s, t; 7817dd7cddfSDavid du Colombier 7827dd7cddfSDavid du Colombier obdst = bdst; 783*8ccd4a63SDavid du Colombier sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta; 784*8ccd4a63SDavid du Colombier q = bsrc.delta == 4 && bdst.delta == 4; 7857dd7cddfSDavid du Colombier 7867dd7cddfSDavid du Colombier for(i=0; i<dx; i++){ 787*8ccd4a63SDavid du Colombier sa = *bsrc.alpha; 7887dd7cddfSDavid du Colombier ma = *bmask.alpha; 789*8ccd4a63SDavid du Colombier fd = MUL(sa, ma, t); 790*8ccd4a63SDavid du Colombier if(op == DoutS) 791*8ccd4a63SDavid du Colombier fd = 255-fd; 7927dd7cddfSDavid du Colombier 7937dd7cddfSDavid du Colombier if(grey){ 794*8ccd4a63SDavid du Colombier *bdst.grey = MUL(fd, *bdst.grey, t); 7957dd7cddfSDavid du Colombier bsrc.grey += bsrc.delta; 7967dd7cddfSDavid du Colombier bdst.grey += bdst.delta; 7977dd7cddfSDavid du Colombier }else{ 798*8ccd4a63SDavid du Colombier if(q){ 799*8ccd4a63SDavid du Colombier *bdst.rgba = MUL0123(fd, *bdst.rgba, s, t); 800*8ccd4a63SDavid du Colombier bsrc.rgba++; 801*8ccd4a63SDavid du Colombier bdst.rgba++; 802*8ccd4a63SDavid du Colombier bsrc.alpha += sadelta; 803*8ccd4a63SDavid du Colombier bmask.alpha += bmask.delta; 804*8ccd4a63SDavid du Colombier continue; 805*8ccd4a63SDavid du Colombier } 806*8ccd4a63SDavid du Colombier *bdst.red = MUL(fd, *bdst.red, t); 807*8ccd4a63SDavid du Colombier *bdst.grn = MUL(fd, *bdst.grn, t); 808*8ccd4a63SDavid du Colombier *bdst.blu = MUL(fd, *bdst.blu, t); 8097dd7cddfSDavid du Colombier bsrc.red += bsrc.delta; 8107dd7cddfSDavid du Colombier bsrc.blu += bsrc.delta; 8117dd7cddfSDavid du Colombier bsrc.grn += bsrc.delta; 8127dd7cddfSDavid du Colombier bdst.red += bdst.delta; 8137dd7cddfSDavid du Colombier bdst.blu += bdst.delta; 8147dd7cddfSDavid du Colombier bdst.grn += bdst.delta; 8157dd7cddfSDavid du Colombier } 816*8ccd4a63SDavid du Colombier if(bdst.alpha != &ones){ 817*8ccd4a63SDavid du Colombier *bdst.alpha = MUL(fd, *bdst.alpha, t); 818*8ccd4a63SDavid du Colombier bdst.alpha += bdst.delta; 819*8ccd4a63SDavid du Colombier } 8207dd7cddfSDavid du Colombier bmask.alpha += bmask.delta; 821*8ccd4a63SDavid du Colombier bsrc.alpha += sadelta; 822*8ccd4a63SDavid du Colombier } 823*8ccd4a63SDavid du Colombier return obdst; 824*8ccd4a63SDavid du Colombier } 8257dd7cddfSDavid du Colombier 826*8ccd4a63SDavid du Colombier static Buffer 827*8ccd4a63SDavid du Colombier alphacalc2810(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op) 828*8ccd4a63SDavid du Colombier { 829*8ccd4a63SDavid du Colombier Buffer obdst; 830*8ccd4a63SDavid du Colombier int fs, sadelta; 831*8ccd4a63SDavid du Colombier int i, ma, da, q; 832*8ccd4a63SDavid du Colombier ulong s, t; 833*8ccd4a63SDavid du Colombier 834*8ccd4a63SDavid du Colombier obdst = bdst; 835*8ccd4a63SDavid du Colombier sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta; 836*8ccd4a63SDavid du Colombier q = bsrc.delta == 4 && bdst.delta == 4; 837*8ccd4a63SDavid du Colombier 838*8ccd4a63SDavid du Colombier for(i=0; i<dx; i++){ 839*8ccd4a63SDavid du Colombier ma = *bmask.alpha; 840*8ccd4a63SDavid du Colombier da = *bdst.alpha; 841*8ccd4a63SDavid du Colombier if(op == SoutD) 842*8ccd4a63SDavid du Colombier da = 255-da; 843*8ccd4a63SDavid du Colombier fs = ma; 844*8ccd4a63SDavid du Colombier if(op != S) 845*8ccd4a63SDavid du Colombier fs = MUL(fs, da, t); 846*8ccd4a63SDavid du Colombier 847*8ccd4a63SDavid du Colombier if(grey){ 848*8ccd4a63SDavid du Colombier *bdst.grey = MUL(fs, *bsrc.grey, t); 849*8ccd4a63SDavid du Colombier bsrc.grey += bsrc.delta; 850*8ccd4a63SDavid du Colombier bdst.grey += bdst.delta; 851*8ccd4a63SDavid du Colombier }else{ 852*8ccd4a63SDavid du Colombier if(q){ 853*8ccd4a63SDavid du Colombier *bdst.rgba = MUL0123(fs, *bsrc.rgba, s, t); 854*8ccd4a63SDavid du Colombier bsrc.rgba++; 855*8ccd4a63SDavid du Colombier bdst.rgba++; 856*8ccd4a63SDavid du Colombier bmask.alpha += bmask.delta; 857*8ccd4a63SDavid du Colombier bdst.alpha += bdst.delta; 858*8ccd4a63SDavid du Colombier continue; 859*8ccd4a63SDavid du Colombier } 860*8ccd4a63SDavid du Colombier *bdst.red = MUL(fs, *bsrc.red, t); 861*8ccd4a63SDavid du Colombier *bdst.grn = MUL(fs, *bsrc.grn, t); 862*8ccd4a63SDavid du Colombier *bdst.blu = MUL(fs, *bsrc.blu, t); 863*8ccd4a63SDavid du Colombier bsrc.red += bsrc.delta; 864*8ccd4a63SDavid du Colombier bsrc.blu += bsrc.delta; 865*8ccd4a63SDavid du Colombier bsrc.grn += bsrc.delta; 866*8ccd4a63SDavid du Colombier bdst.red += bdst.delta; 867*8ccd4a63SDavid du Colombier bdst.blu += bdst.delta; 868*8ccd4a63SDavid du Colombier bdst.grn += bdst.delta; 869*8ccd4a63SDavid du Colombier } 870*8ccd4a63SDavid du Colombier if(bdst.alpha != &ones){ 871*8ccd4a63SDavid du Colombier *bdst.alpha = MUL(fs, *bsrc.alpha, t); 872*8ccd4a63SDavid du Colombier bdst.alpha += bdst.delta; 873*8ccd4a63SDavid du Colombier } 874*8ccd4a63SDavid du Colombier bmask.alpha += bmask.delta; 875*8ccd4a63SDavid du Colombier bsrc.alpha += sadelta; 876*8ccd4a63SDavid du Colombier } 877*8ccd4a63SDavid du Colombier return obdst; 878*8ccd4a63SDavid du Colombier } 879*8ccd4a63SDavid du Colombier 880*8ccd4a63SDavid du Colombier static Buffer 881*8ccd4a63SDavid du Colombier alphacalc3679(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op) 882*8ccd4a63SDavid du Colombier { 883*8ccd4a63SDavid du Colombier Buffer obdst; 884*8ccd4a63SDavid du Colombier int fs, fd, sadelta; 885*8ccd4a63SDavid du Colombier int i, sa, ma, da, q; 886*8ccd4a63SDavid du Colombier ulong s, t, u, v; 887*8ccd4a63SDavid du Colombier 888*8ccd4a63SDavid du Colombier obdst = bdst; 889*8ccd4a63SDavid du Colombier sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta; 890*8ccd4a63SDavid du Colombier q = bsrc.delta == 4 && bdst.delta == 4; 891*8ccd4a63SDavid du Colombier 892*8ccd4a63SDavid du Colombier for(i=0; i<dx; i++){ 893*8ccd4a63SDavid du Colombier sa = *bsrc.alpha; 894*8ccd4a63SDavid du Colombier ma = *bmask.alpha; 895*8ccd4a63SDavid du Colombier da = *bdst.alpha; 896*8ccd4a63SDavid du Colombier if(op == SatopD) 897*8ccd4a63SDavid du Colombier fs = MUL(ma, da, t); 898*8ccd4a63SDavid du Colombier else 899*8ccd4a63SDavid du Colombier fs = MUL(ma, 255-da, t); 900*8ccd4a63SDavid du Colombier if(op == DoverS) 901*8ccd4a63SDavid du Colombier fd = 255; 902*8ccd4a63SDavid du Colombier else{ 903*8ccd4a63SDavid du Colombier fd = MUL(sa, ma, t); 904*8ccd4a63SDavid du Colombier if(op != DatopS) 905*8ccd4a63SDavid du Colombier fd = 255-fd; 906*8ccd4a63SDavid du Colombier } 907*8ccd4a63SDavid du Colombier 908*8ccd4a63SDavid du Colombier if(grey){ 909*8ccd4a63SDavid du Colombier *bdst.grey = MUL(fs, *bsrc.grey, s)+MUL(fd, *bdst.grey, t); 910*8ccd4a63SDavid du Colombier bsrc.grey += bsrc.delta; 911*8ccd4a63SDavid du Colombier bdst.grey += bdst.delta; 912*8ccd4a63SDavid du Colombier }else{ 913*8ccd4a63SDavid du Colombier if(q){ 914*8ccd4a63SDavid du Colombier *bdst.rgba = MUL0123(fs, *bsrc.rgba, s, t)+MUL0123(fd, *bdst.rgba, u, v); 915*8ccd4a63SDavid du Colombier bsrc.rgba++; 916*8ccd4a63SDavid du Colombier bdst.rgba++; 917*8ccd4a63SDavid du Colombier bsrc.alpha += sadelta; 918*8ccd4a63SDavid du Colombier bmask.alpha += bmask.delta; 919*8ccd4a63SDavid du Colombier bdst.alpha += bdst.delta; 920*8ccd4a63SDavid du Colombier continue; 921*8ccd4a63SDavid du Colombier } 922*8ccd4a63SDavid du Colombier *bdst.red = MUL(fs, *bsrc.red, s)+MUL(fd, *bdst.red, t); 923*8ccd4a63SDavid du Colombier *bdst.grn = MUL(fs, *bsrc.grn, s)+MUL(fd, *bdst.grn, t); 924*8ccd4a63SDavid du Colombier *bdst.blu = MUL(fs, *bsrc.blu, s)+MUL(fd, *bdst.blu, t); 925*8ccd4a63SDavid du Colombier bsrc.red += bsrc.delta; 926*8ccd4a63SDavid du Colombier bsrc.blu += bsrc.delta; 927*8ccd4a63SDavid du Colombier bsrc.grn += bsrc.delta; 928*8ccd4a63SDavid du Colombier bdst.red += bdst.delta; 929*8ccd4a63SDavid du Colombier bdst.blu += bdst.delta; 930*8ccd4a63SDavid du Colombier bdst.grn += bdst.delta; 931*8ccd4a63SDavid du Colombier } 932*8ccd4a63SDavid du Colombier if(bdst.alpha != &ones){ 933*8ccd4a63SDavid du Colombier *bdst.alpha = MUL(fs, sa, s)+MUL(fd, da, t); 934*8ccd4a63SDavid du Colombier bdst.alpha += bdst.delta; 935*8ccd4a63SDavid du Colombier } 936*8ccd4a63SDavid du Colombier bmask.alpha += bmask.delta; 937*8ccd4a63SDavid du Colombier bsrc.alpha += sadelta; 938*8ccd4a63SDavid du Colombier } 939*8ccd4a63SDavid du Colombier return obdst; 940*8ccd4a63SDavid du Colombier } 941*8ccd4a63SDavid du Colombier 942*8ccd4a63SDavid du Colombier static Buffer 943*8ccd4a63SDavid du Colombier alphacalc5(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op) 944*8ccd4a63SDavid du Colombier { 945*8ccd4a63SDavid du Colombier USED(dx); 946*8ccd4a63SDavid du Colombier USED(grey); 947*8ccd4a63SDavid du Colombier USED(op); 948*8ccd4a63SDavid du Colombier return bdst; 949*8ccd4a63SDavid du Colombier } 950*8ccd4a63SDavid du Colombier 951*8ccd4a63SDavid du Colombier static Buffer 952*8ccd4a63SDavid du Colombier alphacalc11(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op) 953*8ccd4a63SDavid du Colombier { 954*8ccd4a63SDavid du Colombier Buffer obdst; 955*8ccd4a63SDavid du Colombier int fd, sadelta; 956*8ccd4a63SDavid du Colombier int i, sa, ma, q; 957*8ccd4a63SDavid du Colombier ulong s, t, u, v; 958*8ccd4a63SDavid du Colombier 959*8ccd4a63SDavid du Colombier USED(op); 960*8ccd4a63SDavid du Colombier obdst = bdst; 961*8ccd4a63SDavid du Colombier sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta; 962*8ccd4a63SDavid du Colombier q = bsrc.delta == 4 && bdst.delta == 4; 963*8ccd4a63SDavid du Colombier 964*8ccd4a63SDavid du Colombier for(i=0; i<dx; i++){ 965*8ccd4a63SDavid du Colombier sa = *bsrc.alpha; 966*8ccd4a63SDavid du Colombier ma = *bmask.alpha; 967*8ccd4a63SDavid du Colombier fd = 255-MUL(sa, ma, t); 968*8ccd4a63SDavid du Colombier 969*8ccd4a63SDavid du Colombier if(grey){ 970*8ccd4a63SDavid du Colombier *bdst.grey = MUL(ma, *bsrc.grey, s)+MUL(fd, *bdst.grey, t); 971*8ccd4a63SDavid du Colombier bsrc.grey += bsrc.delta; 972*8ccd4a63SDavid du Colombier bdst.grey += bdst.delta; 973*8ccd4a63SDavid du Colombier }else{ 974*8ccd4a63SDavid du Colombier if(q){ 975*8ccd4a63SDavid du Colombier *bdst.rgba = MUL0123(ma, *bsrc.rgba, s, t)+MUL0123(fd, *bdst.rgba, u, v); 976*8ccd4a63SDavid du Colombier bsrc.rgba++; 977*8ccd4a63SDavid du Colombier bdst.rgba++; 978*8ccd4a63SDavid du Colombier bsrc.alpha += sadelta; 979*8ccd4a63SDavid du Colombier bmask.alpha += bmask.delta; 980*8ccd4a63SDavid du Colombier continue; 981*8ccd4a63SDavid du Colombier } 982*8ccd4a63SDavid du Colombier *bdst.red = MUL(ma, *bsrc.red, s)+MUL(fd, *bdst.red, t); 983*8ccd4a63SDavid du Colombier *bdst.grn = MUL(ma, *bsrc.grn, s)+MUL(fd, *bdst.grn, t); 984*8ccd4a63SDavid du Colombier *bdst.blu = MUL(ma, *bsrc.blu, s)+MUL(fd, *bdst.blu, t); 985*8ccd4a63SDavid du Colombier bsrc.red += bsrc.delta; 986*8ccd4a63SDavid du Colombier bsrc.blu += bsrc.delta; 987*8ccd4a63SDavid du Colombier bsrc.grn += bsrc.delta; 988*8ccd4a63SDavid du Colombier bdst.red += bdst.delta; 989*8ccd4a63SDavid du Colombier bdst.blu += bdst.delta; 990*8ccd4a63SDavid du Colombier bdst.grn += bdst.delta; 991*8ccd4a63SDavid du Colombier } 992*8ccd4a63SDavid du Colombier if(bdst.alpha != &ones){ 993*8ccd4a63SDavid du Colombier *bdst.alpha = MUL(ma, sa, s)+MUL(fd, *bdst.alpha, t); 994*8ccd4a63SDavid du Colombier bdst.alpha += bdst.delta; 995*8ccd4a63SDavid du Colombier } 996*8ccd4a63SDavid du Colombier bmask.alpha += bmask.delta; 997*8ccd4a63SDavid du Colombier bsrc.alpha += sadelta; 998*8ccd4a63SDavid du Colombier } 999*8ccd4a63SDavid du Colombier return obdst; 1000*8ccd4a63SDavid du Colombier } 1001*8ccd4a63SDavid du Colombier 1002*8ccd4a63SDavid du Colombier /* 1003*8ccd4a63SDavid du Colombier not used yet 1004*8ccd4a63SDavid du Colombier source and mask alpha 1 1005*8ccd4a63SDavid du Colombier static Buffer 1006*8ccd4a63SDavid du Colombier alphacalcS0(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op) 1007*8ccd4a63SDavid du Colombier { 1008*8ccd4a63SDavid du Colombier Buffer obdst; 1009*8ccd4a63SDavid du Colombier int i; 1010*8ccd4a63SDavid du Colombier 1011*8ccd4a63SDavid du Colombier USED(op); 1012*8ccd4a63SDavid du Colombier obdst = bdst; 1013*8ccd4a63SDavid du Colombier if(bsrc.delta == bdst.delta){ 1014*8ccd4a63SDavid du Colombier memmove(bdst.rgba, bsrc.rgba, dx*bdst.delta); 1015*8ccd4a63SDavid du Colombier return obdst; 1016*8ccd4a63SDavid du Colombier } 1017*8ccd4a63SDavid du Colombier for(i=0; i<dx; i++){ 1018*8ccd4a63SDavid du Colombier if(grey){ 1019*8ccd4a63SDavid du Colombier *bdst.grey = *bsrc.grey; 1020*8ccd4a63SDavid du Colombier bsrc.grey += bsrc.delta; 1021*8ccd4a63SDavid du Colombier bdst.grey += bdst.delta; 1022*8ccd4a63SDavid du Colombier }else{ 1023*8ccd4a63SDavid du Colombier *bdst.red = *bsrc.red; 1024*8ccd4a63SDavid du Colombier *bdst.grn = *bsrc.grn; 1025*8ccd4a63SDavid du Colombier *bdst.blu = *bsrc.blu; 1026*8ccd4a63SDavid du Colombier bsrc.red += bsrc.delta; 1027*8ccd4a63SDavid du Colombier bsrc.blu += bsrc.delta; 1028*8ccd4a63SDavid du Colombier bsrc.grn += bsrc.delta; 1029*8ccd4a63SDavid du Colombier bdst.red += bdst.delta; 1030*8ccd4a63SDavid du Colombier bdst.blu += bdst.delta; 1031*8ccd4a63SDavid du Colombier bdst.grn += bdst.delta; 1032*8ccd4a63SDavid du Colombier } 1033*8ccd4a63SDavid du Colombier if(bdst.alpha != &ones){ 1034*8ccd4a63SDavid du Colombier *bdst.alpha = 255; 10357dd7cddfSDavid du Colombier bdst.alpha += bdst.delta; 10367dd7cddfSDavid du Colombier } 10377dd7cddfSDavid du Colombier } 10387dd7cddfSDavid du Colombier return obdst; 10397dd7cddfSDavid du Colombier } 1040*8ccd4a63SDavid du Colombier */ 10417dd7cddfSDavid du Colombier 1042*8ccd4a63SDavid du Colombier /* source alpha 1 */ 10437dd7cddfSDavid du Colombier static Buffer 1044*8ccd4a63SDavid du Colombier alphacalcS(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op) 10457dd7cddfSDavid du Colombier { 10467dd7cddfSDavid du Colombier Buffer obdst; 1047*8ccd4a63SDavid du Colombier int fd; 10487dd7cddfSDavid du Colombier int i, ma; 1049*8ccd4a63SDavid du Colombier ulong s, t; 10507dd7cddfSDavid du Colombier 1051*8ccd4a63SDavid du Colombier USED(op); 10527dd7cddfSDavid du Colombier obdst = bdst; 1053*8ccd4a63SDavid du Colombier 10547dd7cddfSDavid du Colombier for(i=0; i<dx; i++){ 10557dd7cddfSDavid du Colombier ma = *bmask.alpha; 1056*8ccd4a63SDavid du Colombier fd = 255-ma; 10577dd7cddfSDavid du Colombier 10587dd7cddfSDavid du Colombier if(grey){ 1059*8ccd4a63SDavid du Colombier *bdst.grey = MUL(ma, *bsrc.grey, s)+MUL(fd, *bdst.grey, t); 1060*8ccd4a63SDavid du Colombier bsrc.grey += bsrc.delta; 1061*8ccd4a63SDavid du Colombier bdst.grey += bdst.delta; 1062*8ccd4a63SDavid du Colombier }else{ 1063*8ccd4a63SDavid du Colombier *bdst.red = MUL(ma, *bsrc.red, s)+MUL(fd, *bdst.red, t); 1064*8ccd4a63SDavid du Colombier *bdst.grn = MUL(ma, *bsrc.grn, s)+MUL(fd, *bdst.grn, t); 1065*8ccd4a63SDavid du Colombier *bdst.blu = MUL(ma, *bsrc.blu, s)+MUL(fd, *bdst.blu, t); 1066*8ccd4a63SDavid du Colombier bsrc.red += bsrc.delta; 1067*8ccd4a63SDavid du Colombier bsrc.blu += bsrc.delta; 1068*8ccd4a63SDavid du Colombier bsrc.grn += bsrc.delta; 1069*8ccd4a63SDavid du Colombier bdst.red += bdst.delta; 1070*8ccd4a63SDavid du Colombier bdst.blu += bdst.delta; 1071*8ccd4a63SDavid du Colombier bdst.grn += bdst.delta; 1072*8ccd4a63SDavid du Colombier } 1073*8ccd4a63SDavid du Colombier if(bdst.alpha != &ones){ 1074*8ccd4a63SDavid du Colombier *bdst.alpha = ma+MUL(fd, *bdst.alpha, t); 1075*8ccd4a63SDavid du Colombier bdst.alpha += bdst.delta; 1076*8ccd4a63SDavid du Colombier } 1077*8ccd4a63SDavid du Colombier bmask.alpha += bmask.delta; 1078*8ccd4a63SDavid du Colombier } 1079*8ccd4a63SDavid du Colombier return obdst; 1080*8ccd4a63SDavid du Colombier } 1081*8ccd4a63SDavid du Colombier 1082*8ccd4a63SDavid du Colombier static Buffer 1083*8ccd4a63SDavid du Colombier boolcalc14(Buffer bdst, Buffer b1, Buffer bmask, int dx, int grey, int op) 1084*8ccd4a63SDavid du Colombier { 1085*8ccd4a63SDavid du Colombier Buffer obdst; 1086*8ccd4a63SDavid du Colombier int i, ma, zero; 1087*8ccd4a63SDavid du Colombier 1088*8ccd4a63SDavid du Colombier obdst = bdst; 1089*8ccd4a63SDavid du Colombier 1090*8ccd4a63SDavid du Colombier for(i=0; i<dx; i++){ 1091*8ccd4a63SDavid du Colombier ma = *bmask.alpha; 1092*8ccd4a63SDavid du Colombier zero = ma ? op == DoutS : op == DinS; 1093*8ccd4a63SDavid du Colombier 1094*8ccd4a63SDavid du Colombier if(grey){ 1095*8ccd4a63SDavid du Colombier if(zero) 1096*8ccd4a63SDavid du Colombier *bdst.grey = 0; 1097*8ccd4a63SDavid du Colombier bdst.grey += bdst.delta; 1098*8ccd4a63SDavid du Colombier }else{ 1099*8ccd4a63SDavid du Colombier if(zero) 1100*8ccd4a63SDavid du Colombier *bdst.red = *bdst.grn = *bdst.blu = 0; 1101*8ccd4a63SDavid du Colombier bdst.red += bdst.delta; 1102*8ccd4a63SDavid du Colombier bdst.blu += bdst.delta; 1103*8ccd4a63SDavid du Colombier bdst.grn += bdst.delta; 1104*8ccd4a63SDavid du Colombier } 1105*8ccd4a63SDavid du Colombier bmask.alpha += bmask.delta; 1106*8ccd4a63SDavid du Colombier if(bdst.alpha != &ones){ 1107*8ccd4a63SDavid du Colombier if(zero) 1108*8ccd4a63SDavid du Colombier *bdst.alpha = 0; 1109*8ccd4a63SDavid du Colombier bdst.alpha += bdst.delta; 1110*8ccd4a63SDavid du Colombier } 1111*8ccd4a63SDavid du Colombier } 1112*8ccd4a63SDavid du Colombier return obdst; 1113*8ccd4a63SDavid du Colombier } 1114*8ccd4a63SDavid du Colombier 1115*8ccd4a63SDavid du Colombier static Buffer 1116*8ccd4a63SDavid du Colombier boolcalc236789(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op) 1117*8ccd4a63SDavid du Colombier { 1118*8ccd4a63SDavid du Colombier Buffer obdst; 1119*8ccd4a63SDavid du Colombier int fs, fd; 1120*8ccd4a63SDavid du Colombier int i, ma, da, zero; 1121*8ccd4a63SDavid du Colombier ulong s, t; 1122*8ccd4a63SDavid du Colombier 1123*8ccd4a63SDavid du Colombier obdst = bdst; 1124*8ccd4a63SDavid du Colombier zero = !(op&1); 1125*8ccd4a63SDavid du Colombier 1126*8ccd4a63SDavid du Colombier for(i=0; i<dx; i++){ 1127*8ccd4a63SDavid du Colombier ma = *bmask.alpha; 1128*8ccd4a63SDavid du Colombier da = *bdst.alpha; 1129*8ccd4a63SDavid du Colombier fs = da; 1130*8ccd4a63SDavid du Colombier if(op&2) 1131*8ccd4a63SDavid du Colombier fs = 255-da; 1132*8ccd4a63SDavid du Colombier fd = 0; 1133*8ccd4a63SDavid du Colombier if(op&4) 1134*8ccd4a63SDavid du Colombier fd = 255; 1135*8ccd4a63SDavid du Colombier 1136*8ccd4a63SDavid du Colombier if(grey){ 11377dd7cddfSDavid du Colombier if(ma) 1138*8ccd4a63SDavid du Colombier *bdst.grey = MUL(fs, *bsrc.grey, s)+MUL(fd, *bdst.grey, t); 1139*8ccd4a63SDavid du Colombier else if(zero) 1140*8ccd4a63SDavid du Colombier *bdst.grey = 0; 11417dd7cddfSDavid du Colombier bsrc.grey += bsrc.delta; 11427dd7cddfSDavid du Colombier bdst.grey += bdst.delta; 11437dd7cddfSDavid du Colombier }else{ 11447dd7cddfSDavid du Colombier if(ma){ 1145*8ccd4a63SDavid du Colombier *bdst.red = MUL(fs, *bsrc.red, s)+MUL(fd, *bdst.red, t); 1146*8ccd4a63SDavid du Colombier *bdst.grn = MUL(fs, *bsrc.grn, s)+MUL(fd, *bdst.grn, t); 1147*8ccd4a63SDavid du Colombier *bdst.blu = MUL(fs, *bsrc.blu, s)+MUL(fd, *bdst.blu, t); 11487dd7cddfSDavid du Colombier } 1149*8ccd4a63SDavid du Colombier else if(zero) 1150*8ccd4a63SDavid du Colombier *bdst.red = *bdst.grn = *bdst.blu = 0; 11517dd7cddfSDavid du Colombier bsrc.red += bsrc.delta; 11527dd7cddfSDavid du Colombier bsrc.blu += bsrc.delta; 11537dd7cddfSDavid du Colombier bsrc.grn += bsrc.delta; 11547dd7cddfSDavid du Colombier bdst.red += bdst.delta; 11557dd7cddfSDavid du Colombier bdst.blu += bdst.delta; 11567dd7cddfSDavid du Colombier bdst.grn += bdst.delta; 11577dd7cddfSDavid du Colombier } 11587dd7cddfSDavid du Colombier bmask.alpha += bmask.delta; 1159*8ccd4a63SDavid du Colombier if(bdst.alpha != &ones){ 11607dd7cddfSDavid du Colombier if(ma) 1161*8ccd4a63SDavid du Colombier *bdst.alpha = fs+MUL(fd, da, t); 1162*8ccd4a63SDavid du Colombier else if(zero) 1163*8ccd4a63SDavid du Colombier *bdst.alpha = 0; 11647dd7cddfSDavid du Colombier bdst.alpha += bdst.delta; 11657dd7cddfSDavid du Colombier } 11667dd7cddfSDavid du Colombier } 11677dd7cddfSDavid du Colombier return obdst; 11687dd7cddfSDavid du Colombier } 11697dd7cddfSDavid du Colombier 1170*8ccd4a63SDavid du Colombier static Buffer 1171*8ccd4a63SDavid du Colombier boolcalc1011(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op) 1172*8ccd4a63SDavid du Colombier { 1173*8ccd4a63SDavid du Colombier Buffer obdst; 1174*8ccd4a63SDavid du Colombier int i, ma, zero; 1175*8ccd4a63SDavid du Colombier 1176*8ccd4a63SDavid du Colombier obdst = bdst; 1177*8ccd4a63SDavid du Colombier zero = !(op&1); 1178*8ccd4a63SDavid du Colombier 1179*8ccd4a63SDavid du Colombier for(i=0; i<dx; i++){ 1180*8ccd4a63SDavid du Colombier ma = *bmask.alpha; 1181*8ccd4a63SDavid du Colombier 1182*8ccd4a63SDavid du Colombier if(grey){ 1183*8ccd4a63SDavid du Colombier if(ma) 1184*8ccd4a63SDavid du Colombier *bdst.grey = *bsrc.grey; 1185*8ccd4a63SDavid du Colombier else if(zero) 1186*8ccd4a63SDavid du Colombier *bdst.grey = 0; 1187*8ccd4a63SDavid du Colombier bsrc.grey += bsrc.delta; 1188*8ccd4a63SDavid du Colombier bdst.grey += bdst.delta; 1189*8ccd4a63SDavid du Colombier }else{ 1190*8ccd4a63SDavid du Colombier if(ma){ 1191*8ccd4a63SDavid du Colombier *bdst.red = *bsrc.red; 1192*8ccd4a63SDavid du Colombier *bdst.grn = *bsrc.grn; 1193*8ccd4a63SDavid du Colombier *bdst.blu = *bsrc.blu; 1194*8ccd4a63SDavid du Colombier } 1195*8ccd4a63SDavid du Colombier else if(zero) 1196*8ccd4a63SDavid du Colombier *bdst.red = *bdst.grn = *bdst.blu = 0; 1197*8ccd4a63SDavid du Colombier bsrc.red += bsrc.delta; 1198*8ccd4a63SDavid du Colombier bsrc.blu += bsrc.delta; 1199*8ccd4a63SDavid du Colombier bsrc.grn += bsrc.delta; 1200*8ccd4a63SDavid du Colombier bdst.red += bdst.delta; 1201*8ccd4a63SDavid du Colombier bdst.blu += bdst.delta; 1202*8ccd4a63SDavid du Colombier bdst.grn += bdst.delta; 1203*8ccd4a63SDavid du Colombier } 1204*8ccd4a63SDavid du Colombier bmask.alpha += bmask.delta; 1205*8ccd4a63SDavid du Colombier if(bdst.alpha != &ones){ 1206*8ccd4a63SDavid du Colombier if(ma) 1207*8ccd4a63SDavid du Colombier *bdst.alpha = 255; 1208*8ccd4a63SDavid du Colombier else if(zero) 1209*8ccd4a63SDavid du Colombier *bdst.alpha = 0; 1210*8ccd4a63SDavid du Colombier bdst.alpha += bdst.delta; 1211*8ccd4a63SDavid du Colombier } 1212*8ccd4a63SDavid du Colombier } 1213*8ccd4a63SDavid du Colombier return obdst; 1214*8ccd4a63SDavid du Colombier } 12157dd7cddfSDavid du Colombier /* 12167dd7cddfSDavid du Colombier * Replicated cached scan line read. Call the function listed in the Param, 12177dd7cddfSDavid du Colombier * but cache the result so that for replicated images we only do the work once. 12187dd7cddfSDavid du Colombier */ 12197dd7cddfSDavid du Colombier static Buffer 1220*8ccd4a63SDavid du Colombier replread(Param *p, uchar *s, int y) 12217dd7cddfSDavid du Colombier { 12227dd7cddfSDavid du Colombier Buffer *b; 12237dd7cddfSDavid du Colombier 1224*8ccd4a63SDavid du Colombier USED(s); 12257dd7cddfSDavid du Colombier b = &p->bcache[y]; 12267dd7cddfSDavid du Colombier if((p->bfilled & (1<<y)) == 0){ 12277dd7cddfSDavid du Colombier p->bfilled |= 1<<y; 12287dd7cddfSDavid du Colombier *b = p->replcall(p, p->bufbase+y*p->bufdelta, y); 12297dd7cddfSDavid du Colombier } 12307dd7cddfSDavid du Colombier return *b; 12317dd7cddfSDavid du Colombier } 12327dd7cddfSDavid du Colombier 12337dd7cddfSDavid du Colombier /* 12347dd7cddfSDavid du Colombier * Alpha reading function that simply relabels the grey pointer. 12357dd7cddfSDavid du Colombier */ 12367dd7cddfSDavid du Colombier static Buffer 12377dd7cddfSDavid du Colombier greymaskread(Param *p, uchar *buf, int y) 12387dd7cddfSDavid du Colombier { 12397dd7cddfSDavid du Colombier Buffer b; 12407dd7cddfSDavid du Colombier 12417dd7cddfSDavid du Colombier b = p->greymaskcall(p, buf, y); 12427dd7cddfSDavid du Colombier b.alpha = b.grey; 12437dd7cddfSDavid du Colombier return b; 12447dd7cddfSDavid du Colombier } 12457dd7cddfSDavid du Colombier 12467dd7cddfSDavid du Colombier #define DBG if(0) 12477dd7cddfSDavid du Colombier static Buffer 12487dd7cddfSDavid du Colombier readnbit(Param *p, uchar *buf, int y) 12497dd7cddfSDavid du Colombier { 12507dd7cddfSDavid du Colombier Buffer b; 12517dd7cddfSDavid du Colombier Memimage *img; 12527dd7cddfSDavid du Colombier uchar *repl, *r, *w, *ow, bits; 12537dd7cddfSDavid du Colombier int i, n, sh, depth, x, dx, npack, nbits; 12547dd7cddfSDavid du Colombier 1255*8ccd4a63SDavid du Colombier b.rgba = (ulong*)buf; 12567dd7cddfSDavid du Colombier b.grey = w = buf; 12577dd7cddfSDavid du Colombier b.red = b.blu = b.grn = w; 1258*8ccd4a63SDavid du Colombier b.alpha = &ones; 12597dd7cddfSDavid du Colombier b.delta = 1; 12607dd7cddfSDavid du Colombier 12617dd7cddfSDavid du Colombier dx = p->dx; 12627dd7cddfSDavid du Colombier img = p->img; 12637dd7cddfSDavid du Colombier depth = img->depth; 12647dd7cddfSDavid du Colombier repl = &replbit[depth][0]; 12657dd7cddfSDavid du Colombier npack = 8/depth; 12667dd7cddfSDavid du Colombier sh = 8-depth; 12677dd7cddfSDavid du Colombier 12687dd7cddfSDavid du Colombier /* copy from p->r.min.x until end of repl rectangle */ 12697dd7cddfSDavid du Colombier x = p->r.min.x; 12707dd7cddfSDavid du Colombier n = dx; 12717dd7cddfSDavid du Colombier if(n > p->img->r.max.x - x) 12727dd7cddfSDavid du Colombier n = p->img->r.max.x - x; 12737dd7cddfSDavid du Colombier 12747dd7cddfSDavid du Colombier r = p->bytermin + y*p->bwidth; 12757dd7cddfSDavid du Colombier DBG print("readnbit dx %d %p=%p+%d*%d, *r=%d fetch %d ", dx, r, p->bytermin, y, p->bwidth, *r, n); 12767dd7cddfSDavid du Colombier bits = *r++; 12777dd7cddfSDavid du Colombier nbits = 8; 1278*8ccd4a63SDavid du Colombier if((i=x&(npack-1))){ 12797dd7cddfSDavid du Colombier DBG print("throwaway %d...", i); 12807dd7cddfSDavid du Colombier bits <<= depth*i; 12817dd7cddfSDavid du Colombier nbits -= depth*i; 12827dd7cddfSDavid du Colombier } 12837dd7cddfSDavid du Colombier for(i=0; i<n; i++){ 12847dd7cddfSDavid du Colombier if(nbits == 0){ 12857dd7cddfSDavid du Colombier DBG print("(%.2ux)...", *r); 12867dd7cddfSDavid du Colombier bits = *r++; 12877dd7cddfSDavid du Colombier nbits = 8; 12887dd7cddfSDavid du Colombier } 12897dd7cddfSDavid du Colombier *w++ = repl[bits>>sh]; 12907dd7cddfSDavid du Colombier DBG print("bit %x...", repl[bits>>sh]); 12917dd7cddfSDavid du Colombier bits <<= depth; 12927dd7cddfSDavid du Colombier nbits -= depth; 12937dd7cddfSDavid du Colombier } 12947dd7cddfSDavid du Colombier dx -= n; 12957dd7cddfSDavid du Colombier if(dx == 0) 12967dd7cddfSDavid du Colombier return b; 12977dd7cddfSDavid du Colombier 12987dd7cddfSDavid du Colombier assert(x+i == p->img->r.max.x); 12997dd7cddfSDavid du Colombier 13007dd7cddfSDavid du Colombier /* copy from beginning of repl rectangle until where we were before. */ 13017dd7cddfSDavid du Colombier x = p->img->r.min.x; 13027dd7cddfSDavid du Colombier n = dx; 13037dd7cddfSDavid du Colombier if(n > p->r.min.x - x) 13047dd7cddfSDavid du Colombier n = p->r.min.x - x; 13057dd7cddfSDavid du Colombier 13067dd7cddfSDavid du Colombier r = p->bytey0s + y*p->bwidth; 13077dd7cddfSDavid du Colombier DBG print("x=%d r=%p...", x, r); 13087dd7cddfSDavid du Colombier bits = *r++; 13097dd7cddfSDavid du Colombier nbits = 8; 1310*8ccd4a63SDavid du Colombier if((i=x&(npack-1))){ 13117dd7cddfSDavid du Colombier bits <<= depth*i; 13127dd7cddfSDavid du Colombier nbits -= depth*i; 13137dd7cddfSDavid du Colombier } 13147dd7cddfSDavid du Colombier DBG print("nbits=%d...", nbits); 13157dd7cddfSDavid du Colombier for(i=0; i<n; i++){ 13167dd7cddfSDavid du Colombier if(nbits == 0){ 13177dd7cddfSDavid du Colombier bits = *r++; 13187dd7cddfSDavid du Colombier nbits = 8; 13197dd7cddfSDavid du Colombier } 13207dd7cddfSDavid du Colombier *w++ = repl[bits>>sh]; 13217dd7cddfSDavid du Colombier DBG print("bit %x...", repl[bits>>sh]); 13227dd7cddfSDavid du Colombier bits <<= depth; 13237dd7cddfSDavid du Colombier nbits -= depth; 13247dd7cddfSDavid du Colombier DBG print("bits %x nbits %d...", bits, nbits); 13257dd7cddfSDavid du Colombier } 13267dd7cddfSDavid du Colombier dx -= n; 13277dd7cddfSDavid du Colombier if(dx == 0) 13287dd7cddfSDavid du Colombier return b; 13297dd7cddfSDavid du Colombier 13307dd7cddfSDavid du Colombier assert(dx > 0); 13317dd7cddfSDavid du Colombier /* now we have exactly one full scan line: just replicate the buffer itself until we are done */ 13327dd7cddfSDavid du Colombier ow = buf; 13337dd7cddfSDavid du Colombier while(dx--) 13347dd7cddfSDavid du Colombier *w++ = *ow++; 13357dd7cddfSDavid du Colombier 13367dd7cddfSDavid du Colombier return b; 13377dd7cddfSDavid du Colombier } 13387dd7cddfSDavid du Colombier #undef DBG 13397dd7cddfSDavid du Colombier 13407dd7cddfSDavid du Colombier #define DBG if(0) 13417dd7cddfSDavid du Colombier static void 13427dd7cddfSDavid du Colombier writenbit(Param *p, uchar *w, Buffer src) 13437dd7cddfSDavid du Colombier { 13447dd7cddfSDavid du Colombier uchar *r; 13457dd7cddfSDavid du Colombier ulong bits; 13467dd7cddfSDavid du Colombier int i, sh, depth, npack, nbits, x, ex; 13477dd7cddfSDavid du Colombier 13487dd7cddfSDavid du Colombier assert(src.grey != nil && src.delta == 1); 13497dd7cddfSDavid du Colombier 13507dd7cddfSDavid du Colombier x = p->r.min.x; 13517dd7cddfSDavid du Colombier ex = x+p->dx; 13527dd7cddfSDavid du Colombier depth = p->img->depth; 13537dd7cddfSDavid du Colombier npack = 8/depth; 13547dd7cddfSDavid du Colombier 13557dd7cddfSDavid du Colombier i=x&(npack-1); 13567dd7cddfSDavid du Colombier bits = i ? (*w >> (8-depth*i)) : 0; 13577dd7cddfSDavid du Colombier nbits = depth*i; 13587dd7cddfSDavid du Colombier sh = 8-depth; 13597dd7cddfSDavid du Colombier r = src.grey; 13607dd7cddfSDavid du Colombier 13617dd7cddfSDavid du Colombier for(; x<ex; x++){ 13627dd7cddfSDavid du Colombier bits <<= depth; 13637dd7cddfSDavid du Colombier DBG print(" %x", *r); 13647dd7cddfSDavid du Colombier bits |= (*r++ >> sh); 13657dd7cddfSDavid du Colombier nbits += depth; 13667dd7cddfSDavid du Colombier if(nbits == 8){ 13677dd7cddfSDavid du Colombier *w++ = bits; 13687dd7cddfSDavid du Colombier nbits = 0; 13697dd7cddfSDavid du Colombier } 13707dd7cddfSDavid du Colombier } 13717dd7cddfSDavid du Colombier 13727dd7cddfSDavid du Colombier if(nbits){ 13737dd7cddfSDavid du Colombier sh = 8-nbits; 13747dd7cddfSDavid du Colombier bits <<= sh; 13757dd7cddfSDavid du Colombier bits |= *w & ((1<<sh)-1); 13767dd7cddfSDavid du Colombier *w = bits; 13777dd7cddfSDavid du Colombier } 13787dd7cddfSDavid du Colombier DBG print("\n"); 13797dd7cddfSDavid du Colombier return; 13807dd7cddfSDavid du Colombier } 13817dd7cddfSDavid du Colombier #undef DBG 13827dd7cddfSDavid du Colombier 13837dd7cddfSDavid du Colombier static Buffer 13847dd7cddfSDavid du Colombier readcmap(Param *p, uchar *buf, int y) 13857dd7cddfSDavid du Colombier { 13867dd7cddfSDavid du Colombier Buffer b; 1387*8ccd4a63SDavid du Colombier int a, convgrey, copyalpha, dx, i, m; 13887dd7cddfSDavid du Colombier uchar *q, *cmap, *begin, *end, *r, *w; 13897dd7cddfSDavid du Colombier 13907dd7cddfSDavid du Colombier begin = p->bytey0s + y*p->bwidth; 13917dd7cddfSDavid du Colombier r = p->bytermin + y*p->bwidth; 13927dd7cddfSDavid du Colombier end = p->bytey0e + y*p->bwidth; 13937dd7cddfSDavid du Colombier cmap = p->img->cmap->cmap2rgb; 13947dd7cddfSDavid du Colombier convgrey = p->convgrey; 1395*8ccd4a63SDavid du Colombier copyalpha = (p->img->flags&Falpha) ? 1 : 0; 13967dd7cddfSDavid du Colombier 13977dd7cddfSDavid du Colombier w = buf; 13987dd7cddfSDavid du Colombier dx = p->dx; 1399*8ccd4a63SDavid du Colombier if(copyalpha){ 1400*8ccd4a63SDavid du Colombier b.alpha = buf++; 1401*8ccd4a63SDavid du Colombier a = p->img->shift[CAlpha]/8; 1402*8ccd4a63SDavid du Colombier m = p->img->shift[CMap]/8; 1403*8ccd4a63SDavid du Colombier for(i=0; i<dx; i++){ 1404*8ccd4a63SDavid du Colombier *w++ = r[a]; 1405*8ccd4a63SDavid du Colombier q = cmap+r[m]*3; 1406*8ccd4a63SDavid du Colombier r += 2; 1407*8ccd4a63SDavid du Colombier if(r == end) 1408*8ccd4a63SDavid du Colombier r = begin; 1409*8ccd4a63SDavid du Colombier if(convgrey){ 1410*8ccd4a63SDavid du Colombier *w++ = RGB2K(q[0], q[1], q[2]); 1411*8ccd4a63SDavid du Colombier }else{ 1412*8ccd4a63SDavid du Colombier *w++ = q[2]; /* blue */ 1413*8ccd4a63SDavid du Colombier *w++ = q[1]; /* green */ 1414*8ccd4a63SDavid du Colombier *w++ = q[0]; /* red */ 1415*8ccd4a63SDavid du Colombier } 1416*8ccd4a63SDavid du Colombier } 1417*8ccd4a63SDavid du Colombier }else{ 1418*8ccd4a63SDavid du Colombier b.alpha = &ones; 14197dd7cddfSDavid du Colombier for(i=0; i<dx; i++){ 14207dd7cddfSDavid du Colombier q = cmap+*r++*3; 14217dd7cddfSDavid du Colombier if(r == end) 14227dd7cddfSDavid du Colombier r = begin; 14237dd7cddfSDavid du Colombier if(convgrey){ 14247dd7cddfSDavid du Colombier *w++ = RGB2K(q[0], q[1], q[2]); 14257dd7cddfSDavid du Colombier }else{ 14267dd7cddfSDavid du Colombier *w++ = q[2]; /* blue */ 14277dd7cddfSDavid du Colombier *w++ = q[1]; /* green */ 14287dd7cddfSDavid du Colombier *w++ = q[0]; /* red */ 14297dd7cddfSDavid du Colombier } 14307dd7cddfSDavid du Colombier } 1431*8ccd4a63SDavid du Colombier } 1432*8ccd4a63SDavid du Colombier 1433*8ccd4a63SDavid du Colombier b.rgba = (ulong*)(buf-copyalpha); 14347dd7cddfSDavid du Colombier 14357dd7cddfSDavid du Colombier if(convgrey){ 14367dd7cddfSDavid du Colombier b.grey = buf; 14377dd7cddfSDavid du Colombier b.red = b.blu = b.grn = buf; 1438*8ccd4a63SDavid du Colombier b.delta = 1+copyalpha; 14397dd7cddfSDavid du Colombier }else{ 14407dd7cddfSDavid du Colombier b.blu = buf; 14417dd7cddfSDavid du Colombier b.grn = buf+1; 14427dd7cddfSDavid du Colombier b.red = buf+2; 14437dd7cddfSDavid du Colombier b.grey = nil; 1444*8ccd4a63SDavid du Colombier b.delta = 3+copyalpha; 14457dd7cddfSDavid du Colombier } 14467dd7cddfSDavid du Colombier return b; 14477dd7cddfSDavid du Colombier } 14487dd7cddfSDavid du Colombier 14497dd7cddfSDavid du Colombier static void 14507dd7cddfSDavid du Colombier writecmap(Param *p, uchar *w, Buffer src) 14517dd7cddfSDavid du Colombier { 14527dd7cddfSDavid du Colombier uchar *cmap, *red, *grn, *blu; 14537dd7cddfSDavid du Colombier int i, dx, delta; 14547dd7cddfSDavid du Colombier 14557dd7cddfSDavid du Colombier cmap = p->img->cmap->rgb2cmap; 14567dd7cddfSDavid du Colombier 14577dd7cddfSDavid du Colombier delta = src.delta; 14587dd7cddfSDavid du Colombier red= src.red; 14597dd7cddfSDavid du Colombier grn = src.grn; 14607dd7cddfSDavid du Colombier blu = src.blu; 14617dd7cddfSDavid du Colombier 14627dd7cddfSDavid du Colombier dx = p->dx; 14637dd7cddfSDavid du Colombier for(i=0; i<dx; i++, red+=delta, grn+=delta, blu+=delta) 14647dd7cddfSDavid du Colombier *w++ = cmap[(*red>>4)*256+(*grn>>4)*16+(*blu>>4)]; 14657dd7cddfSDavid du Colombier } 14667dd7cddfSDavid du Colombier 1467*8ccd4a63SDavid du Colombier #define DBG if(0) 14687dd7cddfSDavid du Colombier static Buffer 14697dd7cddfSDavid du Colombier readbyte(Param *p, uchar *buf, int y) 14707dd7cddfSDavid du Colombier { 14717dd7cddfSDavid du Colombier Buffer b; 14727dd7cddfSDavid du Colombier Memimage *img; 14737dd7cddfSDavid du Colombier int dx, isgrey, convgrey, alphaonly, copyalpha, i, nb; 14747dd7cddfSDavid du Colombier uchar *begin, *end, *r, *w, *rrepl, *grepl, *brepl, *arepl, *krepl; 14757dd7cddfSDavid du Colombier uchar ured, ugrn, ublu; 14767dd7cddfSDavid du Colombier ulong u; 14777dd7cddfSDavid du Colombier 14787dd7cddfSDavid du Colombier img = p->img; 14797dd7cddfSDavid du Colombier begin = p->bytey0s + y*p->bwidth; 14807dd7cddfSDavid du Colombier r = p->bytermin + y*p->bwidth; 14817dd7cddfSDavid du Colombier end = p->bytey0e + y*p->bwidth; 14827dd7cddfSDavid du Colombier 14837dd7cddfSDavid du Colombier w = buf; 14847dd7cddfSDavid du Colombier dx = p->dx; 14857dd7cddfSDavid du Colombier nb = img->depth/8; 14867dd7cddfSDavid du Colombier 14877dd7cddfSDavid du Colombier convgrey = p->convgrey; /* convert rgb to grey */ 14887dd7cddfSDavid du Colombier isgrey = img->flags&Fgrey; 14897dd7cddfSDavid du Colombier alphaonly = p->alphaonly; 149059cc4ca5SDavid du Colombier copyalpha = (img->flags&Falpha) ? 1 : 0; 14917dd7cddfSDavid du Colombier 1492*8ccd4a63SDavid du Colombier DBG print("copyalpha %d alphaonly %d convgrey %d isgrey %d\n", copyalpha, alphaonly, convgrey, isgrey); 14937dd7cddfSDavid du Colombier /* if we can, avoid processing everything */ 14947dd7cddfSDavid du Colombier if(!(img->flags&Frepl) && !convgrey && (img->flags&Fbytes)){ 14957dd7cddfSDavid du Colombier memset(&b, 0, sizeof b); 14967dd7cddfSDavid du Colombier if(p->needbuf){ 14977dd7cddfSDavid du Colombier memmove(buf, r, dx*nb); 14987dd7cddfSDavid du Colombier r = buf; 14997dd7cddfSDavid du Colombier } 1500*8ccd4a63SDavid du Colombier b.rgba = (ulong*)r; 15017dd7cddfSDavid du Colombier if(copyalpha) 15027dd7cddfSDavid du Colombier b.alpha = r+img->shift[CAlpha]/8; 1503*8ccd4a63SDavid du Colombier else 1504*8ccd4a63SDavid du Colombier b.alpha = &ones; 15057dd7cddfSDavid du Colombier if(isgrey){ 15067dd7cddfSDavid du Colombier b.grey = r+img->shift[CGrey]/8; 15077dd7cddfSDavid du Colombier b.red = b.grn = b.blu = b.grey; 15087dd7cddfSDavid du Colombier }else{ 15097dd7cddfSDavid du Colombier b.red = r+img->shift[CRed]/8; 15107dd7cddfSDavid du Colombier b.grn = r+img->shift[CGreen]/8; 15117dd7cddfSDavid du Colombier b.blu = r+img->shift[CBlue]/8; 15127dd7cddfSDavid du Colombier } 15137dd7cddfSDavid du Colombier b.delta = nb; 15147dd7cddfSDavid du Colombier return b; 15157dd7cddfSDavid du Colombier } 15167dd7cddfSDavid du Colombier 1517*8ccd4a63SDavid du Colombier DBG print("2\n"); 15187dd7cddfSDavid du Colombier rrepl = replbit[img->nbits[CRed]]; 15197dd7cddfSDavid du Colombier grepl = replbit[img->nbits[CGreen]]; 15207dd7cddfSDavid du Colombier brepl = replbit[img->nbits[CBlue]]; 15217dd7cddfSDavid du Colombier arepl = replbit[img->nbits[CAlpha]]; 15227dd7cddfSDavid du Colombier krepl = replbit[img->nbits[CGrey]]; 15237dd7cddfSDavid du Colombier 15247dd7cddfSDavid du Colombier for(i=0; i<dx; i++){ 15257dd7cddfSDavid du Colombier u = r[0] | (r[1]<<8) | (r[2]<<16) | (r[3]<<24); 1526*8ccd4a63SDavid du Colombier if(copyalpha) { 15277dd7cddfSDavid du Colombier *w++ = arepl[(u>>img->shift[CAlpha]) & img->mask[CAlpha]]; 1528*8ccd4a63SDavid du Colombier DBG print("a %x\n", w[-1]); 1529*8ccd4a63SDavid du Colombier } 15307dd7cddfSDavid du Colombier 15317dd7cddfSDavid du Colombier if(isgrey) 15327dd7cddfSDavid du Colombier *w++ = krepl[(u >> img->shift[CGrey]) & img->mask[CGrey]]; 15337dd7cddfSDavid du Colombier else if(!alphaonly){ 15347dd7cddfSDavid du Colombier ured = rrepl[(u >> img->shift[CRed]) & img->mask[CRed]]; 15357dd7cddfSDavid du Colombier ugrn = grepl[(u >> img->shift[CGreen]) & img->mask[CGreen]]; 15367dd7cddfSDavid du Colombier ublu = brepl[(u >> img->shift[CBlue]) & img->mask[CBlue]]; 15377dd7cddfSDavid du Colombier if(convgrey){ 1538*8ccd4a63SDavid du Colombier DBG print("g %x %x %x\n", ured, ugrn, ublu); 15397dd7cddfSDavid du Colombier *w++ = RGB2K(ured, ugrn, ublu); 1540*8ccd4a63SDavid du Colombier DBG print("%x\n", w[-1]); 15417dd7cddfSDavid du Colombier }else{ 15427dd7cddfSDavid du Colombier *w++ = brepl[(u >> img->shift[CBlue]) & img->mask[CBlue]]; 15437dd7cddfSDavid du Colombier *w++ = grepl[(u >> img->shift[CGreen]) & img->mask[CGreen]]; 15447dd7cddfSDavid du Colombier *w++ = rrepl[(u >> img->shift[CRed]) & img->mask[CRed]]; 15457dd7cddfSDavid du Colombier } 15467dd7cddfSDavid du Colombier } 15477dd7cddfSDavid du Colombier r += nb; 15487dd7cddfSDavid du Colombier if(r == end) 15497dd7cddfSDavid du Colombier r = begin; 15507dd7cddfSDavid du Colombier } 15517dd7cddfSDavid du Colombier 1552*8ccd4a63SDavid du Colombier b.alpha = copyalpha ? buf : &ones; 1553*8ccd4a63SDavid du Colombier b.rgba = (ulong*)buf; 15547dd7cddfSDavid du Colombier if(alphaonly){ 15557dd7cddfSDavid du Colombier b.red = b.grn = b.blu = b.grey = nil; 1556*8ccd4a63SDavid du Colombier if(!copyalpha) 1557*8ccd4a63SDavid du Colombier b.rgba = nil; 15587dd7cddfSDavid du Colombier b.delta = 1; 15597dd7cddfSDavid du Colombier }else if(isgrey || convgrey){ 15607dd7cddfSDavid du Colombier b.grey = buf+copyalpha; 15617dd7cddfSDavid du Colombier b.red = b.grn = b.blu = buf+copyalpha; 15627dd7cddfSDavid du Colombier b.delta = copyalpha+1; 1563*8ccd4a63SDavid du Colombier DBG print("alpha %x grey %x\n", b.alpha ? *b.alpha : 0xFF, *b.grey); 15647dd7cddfSDavid du Colombier }else{ 15657dd7cddfSDavid du Colombier b.blu = buf+copyalpha; 15667dd7cddfSDavid du Colombier b.grn = buf+copyalpha+1; 15677dd7cddfSDavid du Colombier b.grey = nil; 15687dd7cddfSDavid du Colombier b.red = buf+copyalpha+2; 15697dd7cddfSDavid du Colombier b.delta = copyalpha+3; 15707dd7cddfSDavid du Colombier } 15717dd7cddfSDavid du Colombier return b; 15727dd7cddfSDavid du Colombier } 1573*8ccd4a63SDavid du Colombier #undef DBG 15747dd7cddfSDavid du Colombier 15757dd7cddfSDavid du Colombier #define DBG if(0) 15767dd7cddfSDavid du Colombier static void 15777dd7cddfSDavid du Colombier writebyte(Param *p, uchar *w, Buffer src) 15787dd7cddfSDavid du Colombier { 15797dd7cddfSDavid du Colombier Memimage *img; 15807dd7cddfSDavid du Colombier int i, isalpha, isgrey, nb, delta, dx, adelta; 15817dd7cddfSDavid du Colombier uchar ff, *red, *grn, *blu, *grey, *alpha; 15827dd7cddfSDavid du Colombier ulong u, mask; 15837dd7cddfSDavid du Colombier 15847dd7cddfSDavid du Colombier img = p->img; 15857dd7cddfSDavid du Colombier 15867dd7cddfSDavid du Colombier red = src.red; 15877dd7cddfSDavid du Colombier grn = src.grn; 15887dd7cddfSDavid du Colombier blu = src.blu; 15897dd7cddfSDavid du Colombier alpha = src.alpha; 15907dd7cddfSDavid du Colombier delta = src.delta; 15917dd7cddfSDavid du Colombier grey = src.grey; 15927dd7cddfSDavid du Colombier dx = p->dx; 15937dd7cddfSDavid du Colombier 15947dd7cddfSDavid du Colombier nb = img->depth/8; 15957dd7cddfSDavid du Colombier mask = (nb==4) ? 0 : ~((1<<img->depth)-1); 15967dd7cddfSDavid du Colombier 15977dd7cddfSDavid du Colombier isalpha = img->flags&Falpha; 15987dd7cddfSDavid du Colombier isgrey = img->flags&Fgrey; 15997dd7cddfSDavid du Colombier adelta = src.delta; 16007dd7cddfSDavid du Colombier 1601*8ccd4a63SDavid du Colombier if(isalpha && (alpha == nil || alpha == &ones)){ 16027dd7cddfSDavid du Colombier ff = 0xFF; 16037dd7cddfSDavid du Colombier alpha = &ff; 16047dd7cddfSDavid du Colombier adelta = 0; 16057dd7cddfSDavid du Colombier } 16067dd7cddfSDavid du Colombier 16077dd7cddfSDavid du Colombier for(i=0; i<dx; i++){ 16087dd7cddfSDavid du Colombier u = w[0] | (w[1]<<8) | (w[2]<<16) | (w[3]<<24); 16097dd7cddfSDavid du Colombier DBG print("u %.8lux...", u); 16107dd7cddfSDavid du Colombier u &= mask; 16117dd7cddfSDavid du Colombier DBG print("&mask %.8lux...", u); 16127dd7cddfSDavid du Colombier if(isgrey){ 16137dd7cddfSDavid du Colombier u |= ((*grey >> (8-img->nbits[CGrey])) & img->mask[CGrey]) << img->shift[CGrey]; 16147dd7cddfSDavid du Colombier DBG print("|grey %.8lux...", u); 16157dd7cddfSDavid du Colombier grey += delta; 16167dd7cddfSDavid du Colombier }else{ 16177dd7cddfSDavid du Colombier u |= ((*red >> (8-img->nbits[CRed])) & img->mask[CRed]) << img->shift[CRed]; 16187dd7cddfSDavid du Colombier u |= ((*grn >> (8-img->nbits[CGreen])) & img->mask[CGreen]) << img->shift[CGreen]; 16197dd7cddfSDavid du Colombier u |= ((*blu >> (8-img->nbits[CBlue])) & img->mask[CBlue]) << img->shift[CBlue]; 16207dd7cddfSDavid du Colombier red += delta; 16217dd7cddfSDavid du Colombier grn += delta; 16227dd7cddfSDavid du Colombier blu += delta; 16237dd7cddfSDavid du Colombier DBG print("|rgb %.8lux...", u); 16247dd7cddfSDavid du Colombier } 16257dd7cddfSDavid du Colombier 16267dd7cddfSDavid du Colombier if(isalpha){ 16277dd7cddfSDavid du Colombier u |= ((*alpha >> (8-img->nbits[CAlpha])) & img->mask[CAlpha]) << img->shift[CAlpha]; 16287dd7cddfSDavid du Colombier alpha += adelta; 16297dd7cddfSDavid du Colombier DBG print("|alpha %.8lux...", u); 16307dd7cddfSDavid du Colombier } 16317dd7cddfSDavid du Colombier 16327dd7cddfSDavid du Colombier w[0] = u; 16337dd7cddfSDavid du Colombier w[1] = u>>8; 16347dd7cddfSDavid du Colombier w[2] = u>>16; 16357dd7cddfSDavid du Colombier w[3] = u>>24; 16367dd7cddfSDavid du Colombier w += nb; 16377dd7cddfSDavid du Colombier } 16387dd7cddfSDavid du Colombier } 16397dd7cddfSDavid du Colombier #undef DBG 16407dd7cddfSDavid du Colombier 16417dd7cddfSDavid du Colombier static Readfn* 16427dd7cddfSDavid du Colombier readfn(Memimage *img) 16437dd7cddfSDavid du Colombier { 16447dd7cddfSDavid du Colombier if(img->depth < 8) 16457dd7cddfSDavid du Colombier return readnbit; 1646*8ccd4a63SDavid du Colombier if(img->nbits[CMap] == 8) 16477dd7cddfSDavid du Colombier return readcmap; 16487dd7cddfSDavid du Colombier return readbyte; 16497dd7cddfSDavid du Colombier } 16507dd7cddfSDavid du Colombier 16517dd7cddfSDavid du Colombier static Readfn* 1652*8ccd4a63SDavid du Colombier readalphafn(Memimage *m) 16537dd7cddfSDavid du Colombier { 1654*8ccd4a63SDavid du Colombier USED(m); 16557dd7cddfSDavid du Colombier return readbyte; 16567dd7cddfSDavid du Colombier } 16577dd7cddfSDavid du Colombier 16587dd7cddfSDavid du Colombier static Writefn* 16597dd7cddfSDavid du Colombier writefn(Memimage *img) 16607dd7cddfSDavid du Colombier { 16617dd7cddfSDavid du Colombier if(img->depth < 8) 16627dd7cddfSDavid du Colombier return writenbit; 16637dd7cddfSDavid du Colombier if(img->chan == CMAP8) 16647dd7cddfSDavid du Colombier return writecmap; 16657dd7cddfSDavid du Colombier return writebyte; 16667dd7cddfSDavid du Colombier } 16677dd7cddfSDavid du Colombier 16687dd7cddfSDavid du Colombier static void 1669*8ccd4a63SDavid du Colombier nullwrite(Param *p, uchar *s, Buffer b) 16707dd7cddfSDavid du Colombier { 1671*8ccd4a63SDavid du Colombier USED(p); 1672*8ccd4a63SDavid du Colombier USED(s); 16737dd7cddfSDavid du Colombier } 16747dd7cddfSDavid du Colombier 16757dd7cddfSDavid du Colombier static Buffer 1676*8ccd4a63SDavid du Colombier readptr(Param *p, uchar *s, int y) 16777dd7cddfSDavid du Colombier { 16787dd7cddfSDavid du Colombier Buffer b; 16797dd7cddfSDavid du Colombier uchar *q; 16807dd7cddfSDavid du Colombier 1681*8ccd4a63SDavid du Colombier USED(s); 16827dd7cddfSDavid du Colombier q = p->bytermin + y*p->bwidth; 16837dd7cddfSDavid du Colombier b.red = q; /* ptr to data */ 16847dd7cddfSDavid du Colombier b.grn = b.blu = b.grey = b.alpha = nil; 1685*8ccd4a63SDavid du Colombier b.rgba = (ulong*)q; 16867dd7cddfSDavid du Colombier b.delta = p->img->depth/8; 16877dd7cddfSDavid du Colombier return b; 16887dd7cddfSDavid du Colombier } 16897dd7cddfSDavid du Colombier 16907dd7cddfSDavid du Colombier static Buffer 1691*8ccd4a63SDavid du Colombier boolmemmove(Buffer bdst, Buffer bsrc, Buffer b1, int dx, int i, int o) 16927dd7cddfSDavid du Colombier { 1693*8ccd4a63SDavid du Colombier USED(i); 1694*8ccd4a63SDavid du Colombier USED(o); 16957dd7cddfSDavid du Colombier memmove(bdst.red, bsrc.red, dx*bdst.delta); 16967dd7cddfSDavid du Colombier return bdst; 16977dd7cddfSDavid du Colombier } 16987dd7cddfSDavid du Colombier 16997dd7cddfSDavid du Colombier static Buffer 1700*8ccd4a63SDavid du Colombier boolcopy8(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o) 17017dd7cddfSDavid du Colombier { 17027dd7cddfSDavid du Colombier uchar *m, *r, *w, *ew; 17037dd7cddfSDavid du Colombier 1704*8ccd4a63SDavid du Colombier USED(i); 1705*8ccd4a63SDavid du Colombier USED(o); 17067dd7cddfSDavid du Colombier m = bmask.grey; 17077dd7cddfSDavid du Colombier w = bdst.red; 17087dd7cddfSDavid du Colombier r = bsrc.red; 17097dd7cddfSDavid du Colombier ew = w+dx; 17107dd7cddfSDavid du Colombier for(; w < ew; w++,r++) 17117dd7cddfSDavid du Colombier if(*m++) 17127dd7cddfSDavid du Colombier *w = *r; 17137dd7cddfSDavid du Colombier return bdst; /* not used */ 17147dd7cddfSDavid du Colombier } 17157dd7cddfSDavid du Colombier 17167dd7cddfSDavid du Colombier static Buffer 1717*8ccd4a63SDavid du Colombier boolcopy16(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o) 17187dd7cddfSDavid du Colombier { 17197dd7cddfSDavid du Colombier uchar *m; 17207dd7cddfSDavid du Colombier ushort *r, *w, *ew; 17217dd7cddfSDavid du Colombier 1722*8ccd4a63SDavid du Colombier USED(i); 1723*8ccd4a63SDavid du Colombier USED(o); 17247dd7cddfSDavid du Colombier m = bmask.grey; 17257dd7cddfSDavid du Colombier w = (ushort*)bdst.red; 17267dd7cddfSDavid du Colombier r = (ushort*)bsrc.red; 17277dd7cddfSDavid du Colombier ew = w+dx; 17287dd7cddfSDavid du Colombier for(; w < ew; w++,r++) 17297dd7cddfSDavid du Colombier if(*m++) 17307dd7cddfSDavid du Colombier *w = *r; 17317dd7cddfSDavid du Colombier return bdst; /* not used */ 17327dd7cddfSDavid du Colombier } 17337dd7cddfSDavid du Colombier 17347dd7cddfSDavid du Colombier static Buffer 1735*8ccd4a63SDavid du Colombier boolcopy24(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o) 17367dd7cddfSDavid du Colombier { 17377dd7cddfSDavid du Colombier uchar *m; 17387dd7cddfSDavid du Colombier uchar *r, *w, *ew; 17397dd7cddfSDavid du Colombier 1740*8ccd4a63SDavid du Colombier USED(i); 1741*8ccd4a63SDavid du Colombier USED(o); 17427dd7cddfSDavid du Colombier m = bmask.grey; 17437dd7cddfSDavid du Colombier w = bdst.red; 17447dd7cddfSDavid du Colombier r = bsrc.red; 17457dd7cddfSDavid du Colombier ew = w+dx*3; 17467dd7cddfSDavid du Colombier while(w < ew){ 17477dd7cddfSDavid du Colombier if(*m++){ 17487dd7cddfSDavid du Colombier *w++ = *r++; 17497dd7cddfSDavid du Colombier *w++ = *r++; 17507dd7cddfSDavid du Colombier *w++ = *r++; 17517dd7cddfSDavid du Colombier }else{ 17527dd7cddfSDavid du Colombier w += 3; 17537dd7cddfSDavid du Colombier r += 3; 17547dd7cddfSDavid du Colombier } 17557dd7cddfSDavid du Colombier } 17567dd7cddfSDavid du Colombier return bdst; /* not used */ 17577dd7cddfSDavid du Colombier } 17587dd7cddfSDavid du Colombier 17597dd7cddfSDavid du Colombier static Buffer 1760*8ccd4a63SDavid du Colombier boolcopy32(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o) 17617dd7cddfSDavid du Colombier { 17627dd7cddfSDavid du Colombier uchar *m; 17637dd7cddfSDavid du Colombier ulong *r, *w, *ew; 17647dd7cddfSDavid du Colombier 1765*8ccd4a63SDavid du Colombier USED(i); 1766*8ccd4a63SDavid du Colombier USED(o); 17677dd7cddfSDavid du Colombier m = bmask.grey; 17687dd7cddfSDavid du Colombier w = (ulong*)bdst.red; 17697dd7cddfSDavid du Colombier r = (ulong*)bsrc.red; 17707dd7cddfSDavid du Colombier ew = w+dx; 17717dd7cddfSDavid du Colombier for(; w < ew; w++,r++) 17727dd7cddfSDavid du Colombier if(*m++) 17737dd7cddfSDavid du Colombier *w = *r; 17747dd7cddfSDavid du Colombier return bdst; /* not used */ 17757dd7cddfSDavid du Colombier } 17767dd7cddfSDavid du Colombier 17777dd7cddfSDavid du Colombier static Buffer 17787dd7cddfSDavid du Colombier genconv(Param *p, uchar *buf, int y) 17797dd7cddfSDavid du Colombier { 17807dd7cddfSDavid du Colombier Buffer b; 17817dd7cddfSDavid du Colombier int nb; 17827dd7cddfSDavid du Colombier uchar *r, *w, *ew; 17837dd7cddfSDavid du Colombier 17847dd7cddfSDavid du Colombier /* read from source into RGB format in convbuf */ 17857dd7cddfSDavid du Colombier b = p->convreadcall(p, p->convbuf, y); 17867dd7cddfSDavid du Colombier 17877dd7cddfSDavid du Colombier /* write RGB format into dst format in buf */ 17887dd7cddfSDavid du Colombier p->convwritecall(p->convdpar, buf, b); 17897dd7cddfSDavid du Colombier 17907dd7cddfSDavid du Colombier if(p->convdx){ 17917dd7cddfSDavid du Colombier nb = p->convdpar->img->depth/8; 17927dd7cddfSDavid du Colombier r = buf; 17937dd7cddfSDavid du Colombier w = buf+nb*p->dx; 17947dd7cddfSDavid du Colombier ew = buf+nb*p->convdx; 17957dd7cddfSDavid du Colombier while(w<ew) 17967dd7cddfSDavid du Colombier *w++ = *r++; 17977dd7cddfSDavid du Colombier } 17987dd7cddfSDavid du Colombier 17997dd7cddfSDavid du Colombier b.red = buf; 18007dd7cddfSDavid du Colombier b.blu = b.grn = b.grey = b.alpha = nil; 1801*8ccd4a63SDavid du Colombier b.rgba = (ulong*)buf; 18027dd7cddfSDavid du Colombier b.delta = 0; 18037dd7cddfSDavid du Colombier 18047dd7cddfSDavid du Colombier return b; 18057dd7cddfSDavid du Colombier } 18067dd7cddfSDavid du Colombier 18077dd7cddfSDavid du Colombier static Readfn* 18087dd7cddfSDavid du Colombier convfn(Memimage *dst, Param *dpar, Memimage *src, Param *spar) 18097dd7cddfSDavid du Colombier { 18107dd7cddfSDavid du Colombier if(dst->chan == src->chan && !(src->flags&Frepl)){ 1811*8ccd4a63SDavid du Colombier //if(drawdebug) iprint("readptr..."); 18127dd7cddfSDavid du Colombier return readptr; 18137dd7cddfSDavid du Colombier } 18147dd7cddfSDavid du Colombier 18157dd7cddfSDavid du Colombier if(dst->chan==CMAP8 && (src->chan==GREY1||src->chan==GREY2||src->chan==GREY4)){ 18167dd7cddfSDavid du Colombier /* cheat because we know the replicated value is exactly the color map entry. */ 1817*8ccd4a63SDavid du Colombier //if(drawdebug) iprint("Readnbit..."); 18187dd7cddfSDavid du Colombier return readnbit; 18197dd7cddfSDavid du Colombier } 18207dd7cddfSDavid du Colombier 18217dd7cddfSDavid du Colombier spar->convreadcall = readfn(src); 18227dd7cddfSDavid du Colombier spar->convwritecall = writefn(dst); 18237dd7cddfSDavid du Colombier spar->convdpar = dpar; 18247dd7cddfSDavid du Colombier 18257dd7cddfSDavid du Colombier /* allocate a conversion buffer */ 18267dd7cddfSDavid du Colombier spar->convbufoff = ndrawbuf; 18277dd7cddfSDavid du Colombier ndrawbuf += spar->dx*4; 18287dd7cddfSDavid du Colombier 18297dd7cddfSDavid du Colombier if(spar->dx > Dx(spar->img->r)){ 18307dd7cddfSDavid du Colombier spar->convdx = spar->dx; 18317dd7cddfSDavid du Colombier spar->dx = Dx(spar->img->r); 18327dd7cddfSDavid du Colombier } 18337dd7cddfSDavid du Colombier 1834*8ccd4a63SDavid du Colombier //if(drawdebug) iprint("genconv..."); 18357dd7cddfSDavid du Colombier return genconv; 18367dd7cddfSDavid du Colombier } 18377dd7cddfSDavid du Colombier 18387dd7cddfSDavid du Colombier ulong 18397dd7cddfSDavid du Colombier _pixelbits(Memimage *i, Point pt) 18407dd7cddfSDavid du Colombier { 18417dd7cddfSDavid du Colombier uchar *p; 18427dd7cddfSDavid du Colombier ulong val; 18437dd7cddfSDavid du Colombier int off, bpp, npack; 18447dd7cddfSDavid du Colombier 18457dd7cddfSDavid du Colombier val = 0; 18467dd7cddfSDavid du Colombier p = byteaddr(i, pt); 18477dd7cddfSDavid du Colombier switch(bpp=i->depth){ 18487dd7cddfSDavid du Colombier case 1: 18497dd7cddfSDavid du Colombier case 2: 18507dd7cddfSDavid du Colombier case 4: 18517dd7cddfSDavid du Colombier npack = 8/bpp; 18527dd7cddfSDavid du Colombier off = pt.x%npack; 18537dd7cddfSDavid du Colombier val = p[0] >> bpp*(npack-1-off); 18547dd7cddfSDavid du Colombier val &= (1<<bpp)-1; 18557dd7cddfSDavid du Colombier break; 18567dd7cddfSDavid du Colombier case 8: 18577dd7cddfSDavid du Colombier val = p[0]; 18587dd7cddfSDavid du Colombier break; 18597dd7cddfSDavid du Colombier case 16: 18607dd7cddfSDavid du Colombier val = p[0]|(p[1]<<8); 18617dd7cddfSDavid du Colombier break; 18627dd7cddfSDavid du Colombier case 24: 18637dd7cddfSDavid du Colombier val = p[0]|(p[1]<<8)|(p[2]<<16); 18647dd7cddfSDavid du Colombier break; 18657dd7cddfSDavid du Colombier case 32: 18667dd7cddfSDavid du Colombier val = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24); 18677dd7cddfSDavid du Colombier break; 18687dd7cddfSDavid du Colombier } 18697dd7cddfSDavid du Colombier while(bpp<32){ 18707dd7cddfSDavid du Colombier val |= val<<bpp; 18717dd7cddfSDavid du Colombier bpp *= 2; 18727dd7cddfSDavid du Colombier } 18737dd7cddfSDavid du Colombier return val; 18747dd7cddfSDavid du Colombier } 18757dd7cddfSDavid du Colombier 18767dd7cddfSDavid du Colombier static Calcfn* 18777dd7cddfSDavid du Colombier boolcopyfn(Memimage *img, Memimage *mask) 18787dd7cddfSDavid du Colombier { 1879*8ccd4a63SDavid du Colombier if(mask->flags&Frepl && Dx(mask->r)==1 && Dy(mask->r)==1 && pixelbits(mask, mask->r.min)==~0) 18807dd7cddfSDavid du Colombier return boolmemmove; 18817dd7cddfSDavid du Colombier 18827dd7cddfSDavid du Colombier switch(img->depth){ 18837dd7cddfSDavid du Colombier case 8: 18847dd7cddfSDavid du Colombier return boolcopy8; 18857dd7cddfSDavid du Colombier case 16: 18867dd7cddfSDavid du Colombier return boolcopy16; 18877dd7cddfSDavid du Colombier case 24: 18887dd7cddfSDavid du Colombier return boolcopy24; 18897dd7cddfSDavid du Colombier case 32: 18907dd7cddfSDavid du Colombier return boolcopy32; 18917dd7cddfSDavid du Colombier default: 18927dd7cddfSDavid du Colombier assert(0 /* boolcopyfn */); 18937dd7cddfSDavid du Colombier } 18947dd7cddfSDavid du Colombier return nil; 18957dd7cddfSDavid du Colombier } 18967dd7cddfSDavid du Colombier 18977dd7cddfSDavid du Colombier /* 18987dd7cddfSDavid du Colombier * Optimized draw for filling and scrolling; uses memset and memmove. 1899*8ccd4a63SDavid du Colombier * 19007dd7cddfSDavid du Colombier static void 19017dd7cddfSDavid du Colombier memsetb(void *vp, uchar val, int n) 19027dd7cddfSDavid du Colombier { 19037dd7cddfSDavid du Colombier uchar *p, *ep; 19047dd7cddfSDavid du Colombier 19057dd7cddfSDavid du Colombier p = vp; 19067dd7cddfSDavid du Colombier ep = p+n; 19077dd7cddfSDavid du Colombier while(p<ep) 19087dd7cddfSDavid du Colombier *p++ = val; 19097dd7cddfSDavid du Colombier } 1910*8ccd4a63SDavid du Colombier */ 19117dd7cddfSDavid du Colombier 19127dd7cddfSDavid du Colombier static void 19137dd7cddfSDavid du Colombier memsets(void *vp, ushort val, int n) 19147dd7cddfSDavid du Colombier { 19157dd7cddfSDavid du Colombier ushort *p, *ep; 19167dd7cddfSDavid du Colombier 19177dd7cddfSDavid du Colombier p = vp; 19187dd7cddfSDavid du Colombier ep = p+n; 19197dd7cddfSDavid du Colombier while(p<ep) 19207dd7cddfSDavid du Colombier *p++ = val; 19217dd7cddfSDavid du Colombier } 19227dd7cddfSDavid du Colombier 19237dd7cddfSDavid du Colombier static void 19247dd7cddfSDavid du Colombier memsetl(void *vp, ulong val, int n) 19257dd7cddfSDavid du Colombier { 19267dd7cddfSDavid du Colombier ulong *p, *ep; 19277dd7cddfSDavid du Colombier 19287dd7cddfSDavid du Colombier p = vp; 19297dd7cddfSDavid du Colombier ep = p+n; 19307dd7cddfSDavid du Colombier while(p<ep) 19317dd7cddfSDavid du Colombier *p++ = val; 19327dd7cddfSDavid du Colombier } 19337dd7cddfSDavid du Colombier 1934*8ccd4a63SDavid du Colombier static void 19357dd7cddfSDavid du Colombier memset24(void *vp, ulong val, int n) 19367dd7cddfSDavid du Colombier { 19377dd7cddfSDavid du Colombier uchar *p, *ep; 19387dd7cddfSDavid du Colombier uchar a,b,c; 19397dd7cddfSDavid du Colombier 19407dd7cddfSDavid du Colombier p = vp; 19417dd7cddfSDavid du Colombier ep = p+3*n; 19427dd7cddfSDavid du Colombier a = val; 19437dd7cddfSDavid du Colombier b = val>>8; 19447dd7cddfSDavid du Colombier c = val>>16; 19457dd7cddfSDavid du Colombier while(p<ep){ 19467dd7cddfSDavid du Colombier *p++ = a; 19477dd7cddfSDavid du Colombier *p++ = b; 19487dd7cddfSDavid du Colombier *p++ = c; 19497dd7cddfSDavid du Colombier } 19507dd7cddfSDavid du Colombier } 19517dd7cddfSDavid du Colombier 19527dd7cddfSDavid du Colombier ulong 19537dd7cddfSDavid du Colombier _imgtorgba(Memimage *img, ulong val) 19547dd7cddfSDavid du Colombier { 19557dd7cddfSDavid du Colombier uchar r, g, b, a; 19567dd7cddfSDavid du Colombier int nb, ov, v; 19577dd7cddfSDavid du Colombier ulong chan; 19587dd7cddfSDavid du Colombier uchar *p; 19597dd7cddfSDavid du Colombier 19607dd7cddfSDavid du Colombier a = 0xFF; 19617dd7cddfSDavid du Colombier r = g = b = 0xAA; /* garbage */ 19627dd7cddfSDavid du Colombier for(chan=img->chan; chan; chan>>=8){ 19637dd7cddfSDavid du Colombier nb = NBITS(chan); 19647dd7cddfSDavid du Colombier ov = v = val&((1<<nb)-1); 19657dd7cddfSDavid du Colombier val >>= nb; 19667dd7cddfSDavid du Colombier 19677dd7cddfSDavid du Colombier while(nb < 8){ 19687dd7cddfSDavid du Colombier v |= v<<nb; 19697dd7cddfSDavid du Colombier nb *= 2; 19707dd7cddfSDavid du Colombier } 19717dd7cddfSDavid du Colombier v >>= (nb-8); 19727dd7cddfSDavid du Colombier 19737dd7cddfSDavid du Colombier switch(TYPE(chan)){ 19747dd7cddfSDavid du Colombier case CRed: 19757dd7cddfSDavid du Colombier r = v; 19767dd7cddfSDavid du Colombier break; 19777dd7cddfSDavid du Colombier case CGreen: 19787dd7cddfSDavid du Colombier g = v; 19797dd7cddfSDavid du Colombier break; 19807dd7cddfSDavid du Colombier case CBlue: 19817dd7cddfSDavid du Colombier b = v; 19827dd7cddfSDavid du Colombier break; 19837dd7cddfSDavid du Colombier case CAlpha: 19847dd7cddfSDavid du Colombier a = v; 19857dd7cddfSDavid du Colombier break; 19867dd7cddfSDavid du Colombier case CGrey: 19877dd7cddfSDavid du Colombier r = g = b = v; 19887dd7cddfSDavid du Colombier break; 19897dd7cddfSDavid du Colombier case CMap: 19907dd7cddfSDavid du Colombier p = img->cmap->cmap2rgb+3*ov; 19917dd7cddfSDavid du Colombier r = *p++; 19927dd7cddfSDavid du Colombier g = *p++; 19937dd7cddfSDavid du Colombier b = *p; 19947dd7cddfSDavid du Colombier break; 19957dd7cddfSDavid du Colombier } 19967dd7cddfSDavid du Colombier } 19977dd7cddfSDavid du Colombier return (r<<24)|(g<<16)|(b<<8)|a; 19987dd7cddfSDavid du Colombier } 19997dd7cddfSDavid du Colombier 20007dd7cddfSDavid du Colombier ulong 20017dd7cddfSDavid du Colombier _rgbatoimg(Memimage *img, ulong rgba) 20027dd7cddfSDavid du Colombier { 20037dd7cddfSDavid du Colombier ulong chan; 20047dd7cddfSDavid du Colombier int d, nb; 20057dd7cddfSDavid du Colombier ulong v; 20067dd7cddfSDavid du Colombier uchar *p, r, g, b, a, m; 20077dd7cddfSDavid du Colombier 20087dd7cddfSDavid du Colombier v = 0; 20097dd7cddfSDavid du Colombier r = rgba>>24; 20107dd7cddfSDavid du Colombier g = rgba>>16; 20117dd7cddfSDavid du Colombier b = rgba>>8; 20127dd7cddfSDavid du Colombier a = rgba; 20137dd7cddfSDavid du Colombier d = 0; 20147dd7cddfSDavid du Colombier for(chan=img->chan; chan; chan>>=8){ 20157dd7cddfSDavid du Colombier nb = NBITS(chan); 20167dd7cddfSDavid du Colombier switch(TYPE(chan)){ 20177dd7cddfSDavid du Colombier case CRed: 20187dd7cddfSDavid du Colombier v |= (r>>(8-nb))<<d; 20197dd7cddfSDavid du Colombier break; 20207dd7cddfSDavid du Colombier case CGreen: 20217dd7cddfSDavid du Colombier v |= (g>>(8-nb))<<d; 20227dd7cddfSDavid du Colombier break; 20237dd7cddfSDavid du Colombier case CBlue: 20247dd7cddfSDavid du Colombier v |= (b>>(8-nb))<<d; 20257dd7cddfSDavid du Colombier break; 20267dd7cddfSDavid du Colombier case CAlpha: 20277dd7cddfSDavid du Colombier v |= (a>>(8-nb))<<d; 20287dd7cddfSDavid du Colombier break; 20297dd7cddfSDavid du Colombier case CMap: 20307dd7cddfSDavid du Colombier p = img->cmap->rgb2cmap; 20317dd7cddfSDavid du Colombier m = p[(r>>4)*256+(g>>4)*16+(b>>4)]; 203259cc4ca5SDavid du Colombier v |= (m>>(8-nb))<<d; 20337dd7cddfSDavid du Colombier break; 20347dd7cddfSDavid du Colombier case CGrey: 20357dd7cddfSDavid du Colombier m = RGB2K(r,g,b); 203659cc4ca5SDavid du Colombier v |= (m>>(8-nb))<<d; 20377dd7cddfSDavid du Colombier break; 20387dd7cddfSDavid du Colombier } 20397dd7cddfSDavid du Colombier d += nb; 20407dd7cddfSDavid du Colombier } 2041*8ccd4a63SDavid du Colombier // print("rgba2img %.8lux = %.*lux\n", rgba, 2*d/8, v); 20427dd7cddfSDavid du Colombier return v; 20437dd7cddfSDavid du Colombier } 20447dd7cddfSDavid du Colombier 2045*8ccd4a63SDavid du Colombier #define DBG if(0) 20467dd7cddfSDavid du Colombier static int 20477dd7cddfSDavid du Colombier memoptdraw(Memdrawparam *par) 20487dd7cddfSDavid du Colombier { 2049*8ccd4a63SDavid du Colombier int m, y, dy, dx, op; 20507dd7cddfSDavid du Colombier ulong v; 20517dd7cddfSDavid du Colombier Memimage *src; 20527dd7cddfSDavid du Colombier Memimage *dst; 20537dd7cddfSDavid du Colombier 20547dd7cddfSDavid du Colombier dx = Dx(par->r); 20557dd7cddfSDavid du Colombier dy = Dy(par->r); 20567dd7cddfSDavid du Colombier src = par->src; 20577dd7cddfSDavid du Colombier dst = par->dst; 2058*8ccd4a63SDavid du Colombier op = par->op; 20597dd7cddfSDavid du Colombier 2060*8ccd4a63SDavid du Colombier DBG print("state %lux mval %lux dd %d\n", par->state, par->mval, dst->depth); 20617dd7cddfSDavid du Colombier /* 20627dd7cddfSDavid du Colombier * If we have an opaque mask and source is one opaque pixel we can convert to the 20637dd7cddfSDavid du Colombier * destination format and just replicate with memset. 20647dd7cddfSDavid du Colombier */ 20657dd7cddfSDavid du Colombier m = Simplesrc|Simplemask|Fullmask; 2066*8ccd4a63SDavid du Colombier if((par->state&m)==m && (par->srgba&0xFF) == 0xFF && (op ==S || op == SoverD)){ 20677dd7cddfSDavid du Colombier uchar *dp, p[4]; 206859cc4ca5SDavid du Colombier int d, dwid, ppb, np, nb; 20697dd7cddfSDavid du Colombier uchar lm, rm; 20707dd7cddfSDavid du Colombier 2071*8ccd4a63SDavid du Colombier DBG print("memopt, dst %p, dst->data->bdata %p\n", dst, dst->data->bdata); 20727dd7cddfSDavid du Colombier dwid = dst->width*sizeof(ulong); 20737dd7cddfSDavid du Colombier dp = byteaddr(dst, par->r.min); 20747dd7cddfSDavid du Colombier v = par->sdval; 2075*8ccd4a63SDavid du Colombier DBG print("sdval %lud, depth %d\n", v, dst->depth); 20767dd7cddfSDavid du Colombier switch(dst->depth){ 20777dd7cddfSDavid du Colombier case 1: 20787dd7cddfSDavid du Colombier case 2: 20797dd7cddfSDavid du Colombier case 4: 208059cc4ca5SDavid du Colombier for(d=dst->depth; d<8; d*=2) 208159cc4ca5SDavid du Colombier v |= (v<<d); 20827dd7cddfSDavid du Colombier ppb = 8/dst->depth; /* pixels per byte */ 20837dd7cddfSDavid du Colombier m = ppb-1; 20847dd7cddfSDavid du Colombier /* left edge */ 20857dd7cddfSDavid du Colombier np = par->r.min.x&m; /* no. pixels unused on left side of word */ 20867dd7cddfSDavid du Colombier dx -= (ppb-np); 20877dd7cddfSDavid du Colombier nb = 8 - np * dst->depth; /* no. bits used on right side of word */ 20887dd7cddfSDavid du Colombier lm = (1<<nb)-1; 2089*8ccd4a63SDavid 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); 20907dd7cddfSDavid du Colombier 20917dd7cddfSDavid du Colombier /* right edge */ 20927dd7cddfSDavid du Colombier np = par->r.max.x&m; /* no. pixels used on left side of word */ 20937dd7cddfSDavid du Colombier dx -= np; 20947dd7cddfSDavid du Colombier nb = 8 - np * dst->depth; /* no. bits unused on right side of word */ 20957dd7cddfSDavid du Colombier rm = ~((1<<nb)-1); 2096*8ccd4a63SDavid 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); 20977dd7cddfSDavid du Colombier 2098*8ccd4a63SDavid du Colombier DBG print("dx %d Dx %d\n", dx, Dx(par->r)); 20997dd7cddfSDavid du Colombier /* lm, rm are masks that are 1 where we should touch the bits */ 21007dd7cddfSDavid du Colombier if(dx < 0){ /* just one byte */ 21017dd7cddfSDavid du Colombier lm &= rm; 21027dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid) 21037dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & lm; 21047dd7cddfSDavid du Colombier }else if(dx == 0){ /* no full bytes */ 21057dd7cddfSDavid du Colombier if(lm) 21067dd7cddfSDavid du Colombier dwid--; 21077dd7cddfSDavid du Colombier 21087dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid){ 21097dd7cddfSDavid du Colombier if(lm){ 2110*8ccd4a63SDavid du Colombier DBG print("dp %p v %lux lm %ux (v ^ *dp) & lm %lux\n", dp, v, lm, (v^*dp)&lm); 21117dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & lm; 21127dd7cddfSDavid du Colombier dp++; 21137dd7cddfSDavid du Colombier } 21147dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & rm; 21157dd7cddfSDavid du Colombier } 21167dd7cddfSDavid du Colombier }else{ /* full bytes in middle */ 21177dd7cddfSDavid du Colombier dx /= ppb; 21187dd7cddfSDavid du Colombier if(lm) 21197dd7cddfSDavid du Colombier dwid--; 21207dd7cddfSDavid du Colombier dwid -= dx; 21217dd7cddfSDavid du Colombier 21227dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid){ 21237dd7cddfSDavid du Colombier if(lm){ 21247dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & lm; 21257dd7cddfSDavid du Colombier dp++; 21267dd7cddfSDavid du Colombier } 21277dd7cddfSDavid du Colombier memset(dp, v, dx); 21287dd7cddfSDavid du Colombier dp += dx; 21297dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & rm; 21307dd7cddfSDavid du Colombier } 21317dd7cddfSDavid du Colombier } 21327dd7cddfSDavid du Colombier return 1; 21337dd7cddfSDavid du Colombier case 8: 21347dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid) 21357dd7cddfSDavid du Colombier memset(dp, v, dx); 21367dd7cddfSDavid du Colombier return 1; 21377dd7cddfSDavid du Colombier case 16: 21387dd7cddfSDavid du Colombier p[0] = v; /* make little endian */ 21397dd7cddfSDavid du Colombier p[1] = v>>8; 21407dd7cddfSDavid du Colombier v = *(ushort*)p; 2141*8ccd4a63SDavid du Colombier DBG print("dp=%p; dx=%d; for(y=0; y<%d; y++, dp+=%d)\nmemsets(dp, v, dx);\n", 2142*8ccd4a63SDavid du Colombier dp, dx, dy, dwid); 21437dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid) 21447dd7cddfSDavid du Colombier memsets(dp, v, dx); 21457dd7cddfSDavid du Colombier return 1; 21467dd7cddfSDavid du Colombier case 24: 21477dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid) 21487dd7cddfSDavid du Colombier memset24(dp, v, dx); 21497dd7cddfSDavid du Colombier return 1; 21507dd7cddfSDavid du Colombier case 32: 21517dd7cddfSDavid du Colombier p[0] = v; /* make little endian */ 21527dd7cddfSDavid du Colombier p[1] = v>>8; 21537dd7cddfSDavid du Colombier p[2] = v>>16; 21547dd7cddfSDavid du Colombier p[3] = v>>24; 21557dd7cddfSDavid du Colombier v = *(ulong*)p; 21567dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid) 21577dd7cddfSDavid du Colombier memsetl(dp, v, dx); 21587dd7cddfSDavid du Colombier return 1; 21597dd7cddfSDavid du Colombier default: 21607dd7cddfSDavid du Colombier assert(0 /* bad dest depth in memoptdraw */); 21617dd7cddfSDavid du Colombier } 21627dd7cddfSDavid du Colombier } 21637dd7cddfSDavid du Colombier 21647dd7cddfSDavid du Colombier /* 21657dd7cddfSDavid du Colombier * If no source alpha, an opaque mask, we can just copy the 21667dd7cddfSDavid du Colombier * source onto the destination. If the channels are the same and 21677dd7cddfSDavid du Colombier * the source is not replicated, memmove suffices. 21687dd7cddfSDavid du Colombier */ 21697dd7cddfSDavid du Colombier m = Simplemask|Fullmask; 21707dd7cddfSDavid du Colombier if((par->state&(m|Replsrc))==m && src->depth >= 8 2171*8ccd4a63SDavid du Colombier && src->chan == dst->chan && !(src->flags&Falpha) && (op == S || op == SoverD)){ 21727dd7cddfSDavid du Colombier uchar *sp, *dp; 21737dd7cddfSDavid du Colombier long swid, dwid, nb; 21747dd7cddfSDavid du Colombier int dir; 21757dd7cddfSDavid du Colombier 21767dd7cddfSDavid du Colombier if(src->data == dst->data && byteaddr(dst, par->r.min) > byteaddr(src, par->sr.min)) 21777dd7cddfSDavid du Colombier dir = -1; 21787dd7cddfSDavid du Colombier else 21797dd7cddfSDavid du Colombier dir = 1; 21807dd7cddfSDavid du Colombier 21817dd7cddfSDavid du Colombier swid = src->width*sizeof(ulong); 21827dd7cddfSDavid du Colombier dwid = dst->width*sizeof(ulong); 21837dd7cddfSDavid du Colombier sp = byteaddr(src, par->sr.min); 21847dd7cddfSDavid du Colombier dp = byteaddr(dst, par->r.min); 21857dd7cddfSDavid du Colombier if(dir == -1){ 21867dd7cddfSDavid du Colombier sp += (dy-1)*swid; 21877dd7cddfSDavid du Colombier dp += (dy-1)*dwid; 21887dd7cddfSDavid du Colombier swid = -swid; 21897dd7cddfSDavid du Colombier dwid = -dwid; 21907dd7cddfSDavid du Colombier } 21917dd7cddfSDavid du Colombier nb = (dx*src->depth)/8; 21927dd7cddfSDavid du Colombier for(y=0; y<dy; y++, sp+=swid, dp+=dwid) 21937dd7cddfSDavid du Colombier memmove(dp, sp, nb); 21947dd7cddfSDavid du Colombier return 1; 21957dd7cddfSDavid du Colombier } 21967dd7cddfSDavid du Colombier 21977dd7cddfSDavid du Colombier /* 21987dd7cddfSDavid du Colombier * If we have a 1-bit mask, 1-bit source, and 1-bit destination, and 21997dd7cddfSDavid du Colombier * they're all bit aligned, we can just use bit operators. This happens 22007dd7cddfSDavid du Colombier * when we're manipulating boolean masks, e.g. in the arc code. 22017dd7cddfSDavid du Colombier */ 22027dd7cddfSDavid du Colombier if((par->state&(Simplemask|Simplesrc|Replmask|Replsrc))==0 22037dd7cddfSDavid du Colombier && dst->chan==GREY1 && src->chan==GREY1 && par->mask->chan==GREY1 22047dd7cddfSDavid du Colombier && (par->r.min.x&7)==(par->sr.min.x&7) && (par->r.min.x&7)==(par->mr.min.x&7)){ 22057dd7cddfSDavid du Colombier uchar *sp, *dp, *mp; 22067dd7cddfSDavid du Colombier uchar lm, rm; 22077dd7cddfSDavid du Colombier long swid, dwid, mwid; 22087dd7cddfSDavid du Colombier int i, x, dir; 22097dd7cddfSDavid du Colombier 22107dd7cddfSDavid du Colombier sp = byteaddr(src, par->sr.min); 22117dd7cddfSDavid du Colombier dp = byteaddr(dst, par->r.min); 22127dd7cddfSDavid du Colombier mp = byteaddr(par->mask, par->mr.min); 22137dd7cddfSDavid du Colombier swid = src->width*sizeof(ulong); 22147dd7cddfSDavid du Colombier dwid = dst->width*sizeof(ulong); 22157dd7cddfSDavid du Colombier mwid = par->mask->width*sizeof(ulong); 22167dd7cddfSDavid du Colombier 22177dd7cddfSDavid du Colombier if(src->data == dst->data && byteaddr(dst, par->r.min) > byteaddr(src, par->sr.min)){ 22187dd7cddfSDavid du Colombier dir = -1; 22197dd7cddfSDavid du Colombier }else 22207dd7cddfSDavid du Colombier dir = 1; 22217dd7cddfSDavid du Colombier 22227dd7cddfSDavid du Colombier lm = 0xFF>>(par->r.min.x&7); 22237dd7cddfSDavid du Colombier rm = 0xFF<<(8-(par->r.max.x&7)); 22247dd7cddfSDavid du Colombier dx -= (8-(par->r.min.x&7)) + (par->r.max.x&7); 22257dd7cddfSDavid du Colombier 22267dd7cddfSDavid du Colombier if(dx < 0){ /* one byte wide */ 22277dd7cddfSDavid du Colombier lm &= rm; 22287dd7cddfSDavid du Colombier if(dir == -1){ 22297dd7cddfSDavid du Colombier dp += dwid*(dy-1); 22307dd7cddfSDavid du Colombier sp += swid*(dy-1); 22317dd7cddfSDavid du Colombier mp += mwid*(dy-1); 22327dd7cddfSDavid du Colombier dwid = -dwid; 22337dd7cddfSDavid du Colombier swid = -swid; 22347dd7cddfSDavid du Colombier mwid = -mwid; 22357dd7cddfSDavid du Colombier } 22367dd7cddfSDavid du Colombier for(y=0; y<dy; y++){ 22377dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp) & *mp & lm; 22387dd7cddfSDavid du Colombier dp += dwid; 22397dd7cddfSDavid du Colombier sp += swid; 22407dd7cddfSDavid du Colombier mp += mwid; 22417dd7cddfSDavid du Colombier } 22427dd7cddfSDavid du Colombier return 1; 22437dd7cddfSDavid du Colombier } 22447dd7cddfSDavid du Colombier 22457dd7cddfSDavid du Colombier dx /= 8; 22467dd7cddfSDavid du Colombier if(dir == 1){ 22477dd7cddfSDavid du Colombier i = (lm!=0)+dx+(rm!=0); 22487dd7cddfSDavid du Colombier mwid -= i; 22497dd7cddfSDavid du Colombier swid -= i; 22507dd7cddfSDavid du Colombier dwid -= i; 22517dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid, sp+=swid, mp+=mwid){ 22527dd7cddfSDavid du Colombier if(lm){ 22537dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp++) & *mp++ & lm; 22547dd7cddfSDavid du Colombier dp++; 22557dd7cddfSDavid du Colombier } 22567dd7cddfSDavid du Colombier for(x=0; x<dx; x++){ 22577dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp++) & *mp++; 22587dd7cddfSDavid du Colombier dp++; 22597dd7cddfSDavid du Colombier } 22607dd7cddfSDavid du Colombier if(rm){ 22617dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp++) & *mp++ & rm; 22627dd7cddfSDavid du Colombier dp++; 22637dd7cddfSDavid du Colombier } 22647dd7cddfSDavid du Colombier } 22657dd7cddfSDavid du Colombier return 1; 22667dd7cddfSDavid du Colombier }else{ 22677dd7cddfSDavid du Colombier /* dir == -1 */ 22687dd7cddfSDavid du Colombier i = (lm!=0)+dx+(rm!=0); 22697dd7cddfSDavid du Colombier dp += dwid*(dy-1)+i-1; 22707dd7cddfSDavid du Colombier sp += swid*(dy-1)+i-1; 22717dd7cddfSDavid du Colombier mp += mwid*(dy-1)+i-1; 22727dd7cddfSDavid du Colombier dwid = -dwid+i; 22737dd7cddfSDavid du Colombier swid = -swid+i; 22747dd7cddfSDavid du Colombier mwid = -mwid+i; 22757dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid, sp+=swid, mp+=mwid){ 22767dd7cddfSDavid du Colombier if(rm){ 22777dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp--) & *mp-- & rm; 22787dd7cddfSDavid du Colombier dp--; 22797dd7cddfSDavid du Colombier } 22807dd7cddfSDavid du Colombier for(x=0; x<dx; x++){ 22817dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp--) & *mp--; 22827dd7cddfSDavid du Colombier dp--; 22837dd7cddfSDavid du Colombier } 22847dd7cddfSDavid du Colombier if(lm){ 22857dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp--) & *mp-- & lm; 22867dd7cddfSDavid du Colombier dp--; 22877dd7cddfSDavid du Colombier } 22887dd7cddfSDavid du Colombier } 22897dd7cddfSDavid du Colombier } 22907dd7cddfSDavid du Colombier return 1; 22917dd7cddfSDavid du Colombier } 22927dd7cddfSDavid du Colombier return 0; 22937dd7cddfSDavid du Colombier } 2294*8ccd4a63SDavid du Colombier #undef DBG 22957dd7cddfSDavid du Colombier 22967dd7cddfSDavid du Colombier /* 22977dd7cddfSDavid du Colombier * Boolean character drawing. 22987dd7cddfSDavid du Colombier * Solid opaque color through a 1-bit greyscale mask. 22997dd7cddfSDavid du Colombier */ 23007dd7cddfSDavid du Colombier #define DBG if(0) 23017dd7cddfSDavid du Colombier static int 23027dd7cddfSDavid du Colombier chardraw(Memdrawparam *par) 23037dd7cddfSDavid du Colombier { 23047dd7cddfSDavid du Colombier ulong bits; 2305*8ccd4a63SDavid du Colombier int i, ddepth, dy, dx, x, bx, ex, y, npack, bsh, depth, op; 23067dd7cddfSDavid du Colombier ulong v, maskwid, dstwid; 23077dd7cddfSDavid du Colombier uchar *wp, *rp, *q, *wc; 23087dd7cddfSDavid du Colombier ushort *ws; 23097dd7cddfSDavid du Colombier ulong *wl; 23107dd7cddfSDavid du Colombier uchar sp[4]; 23117dd7cddfSDavid du Colombier Rectangle r, mr; 23127dd7cddfSDavid du Colombier Memimage *mask, *src, *dst; 23137dd7cddfSDavid du Colombier 23147dd7cddfSDavid 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", 23157dd7cddfSDavid du Colombier par->mask->flags, par->mask->depth, par->src->flags, 23167dd7cddfSDavid du Colombier Dx(par->src->r), Dy(par->src->r), par->dst->depth, par->dst->data, par->src->data); 23177dd7cddfSDavid du Colombier 23187dd7cddfSDavid du Colombier mask = par->mask; 23197dd7cddfSDavid du Colombier src = par->src; 23207dd7cddfSDavid du Colombier dst = par->dst; 23217dd7cddfSDavid du Colombier r = par->r; 23227dd7cddfSDavid du Colombier mr = par->mr; 2323*8ccd4a63SDavid du Colombier op = par->op; 23247dd7cddfSDavid du Colombier 23257dd7cddfSDavid du Colombier if((par->state&(Replsrc|Simplesrc|Replmask)) != (Replsrc|Simplesrc) 2326*8ccd4a63SDavid du Colombier || mask->depth != 1 || src->flags&Falpha || dst->depth<8 || dst->data==src->data 2327*8ccd4a63SDavid du Colombier || op != SoverD) 23287dd7cddfSDavid du Colombier return 0; 23297dd7cddfSDavid du Colombier 2330*8ccd4a63SDavid du Colombier //if(drawdebug) iprint("chardraw..."); 2331*8ccd4a63SDavid du Colombier 23327dd7cddfSDavid du Colombier depth = mask->depth; 23337dd7cddfSDavid du Colombier maskwid = mask->width*sizeof(ulong); 23347dd7cddfSDavid du Colombier rp = byteaddr(mask, mr.min); 23357dd7cddfSDavid du Colombier npack = 8/depth; 23367dd7cddfSDavid du Colombier bsh = (mr.min.x % npack) * depth; 23377dd7cddfSDavid du Colombier 23387dd7cddfSDavid du Colombier wp = byteaddr(dst, r.min); 23397dd7cddfSDavid du Colombier dstwid = dst->width*sizeof(ulong); 23407dd7cddfSDavid du Colombier DBG print("bsh %d\n", bsh); 23417dd7cddfSDavid du Colombier dy = Dy(r); 23427dd7cddfSDavid du Colombier dx = Dx(r); 23437dd7cddfSDavid du Colombier 23447dd7cddfSDavid du Colombier ddepth = dst->depth; 23457dd7cddfSDavid du Colombier 23467dd7cddfSDavid du Colombier /* 23477dd7cddfSDavid du Colombier * for loop counts from bsh to bsh+dx 23487dd7cddfSDavid du Colombier * 23497dd7cddfSDavid du Colombier * we want the bottom bits to be the amount 23507dd7cddfSDavid du Colombier * to shift the pixels down, so for n≡0 (mod 8) we want 23517dd7cddfSDavid du Colombier * bottom bits 7. for n≡1, 6, etc. 23527dd7cddfSDavid du Colombier * the bits come from -n-1. 23537dd7cddfSDavid du Colombier */ 23547dd7cddfSDavid du Colombier 23557dd7cddfSDavid du Colombier bx = -bsh-1; 23567dd7cddfSDavid du Colombier ex = -bsh-1-dx; 2357*8ccd4a63SDavid du Colombier bits = 0; 23587dd7cddfSDavid du Colombier v = par->sdval; 23597dd7cddfSDavid du Colombier 23607dd7cddfSDavid du Colombier /* make little endian */ 23617dd7cddfSDavid du Colombier sp[0] = v; 23627dd7cddfSDavid du Colombier sp[1] = v>>8; 23637dd7cddfSDavid du Colombier sp[2] = v>>16; 23647dd7cddfSDavid du Colombier sp[3] = v>>24; 23657dd7cddfSDavid du Colombier 2366*8ccd4a63SDavid du Colombier //print("sp %x %x %x %x\n", sp[0], sp[1], sp[2], sp[3]); 23677dd7cddfSDavid du Colombier for(y=0; y<dy; y++, rp+=maskwid, wp+=dstwid){ 23687dd7cddfSDavid du Colombier q = rp; 23697dd7cddfSDavid du Colombier if(bsh) 23707dd7cddfSDavid du Colombier bits = *q++; 23717dd7cddfSDavid du Colombier switch(ddepth){ 23727dd7cddfSDavid du Colombier case 8: 2373*8ccd4a63SDavid du Colombier //if(drawdebug) iprint("8loop..."); 23747dd7cddfSDavid du Colombier wc = wp; 23757dd7cddfSDavid du Colombier for(x=bx; x>ex; x--, wc++){ 23767dd7cddfSDavid du Colombier i = x&7; 23777dd7cddfSDavid du Colombier if(i == 8-1) 23787dd7cddfSDavid du Colombier bits = *q++; 23797dd7cddfSDavid du Colombier DBG print("bits %lux sh %d...", bits, i); 23807dd7cddfSDavid du Colombier if((bits>>i)&1) 23817dd7cddfSDavid du Colombier *wc = v; 23827dd7cddfSDavid du Colombier } 23837dd7cddfSDavid du Colombier break; 23847dd7cddfSDavid du Colombier case 16: 23857dd7cddfSDavid du Colombier ws = (ushort*)wp; 23867dd7cddfSDavid du Colombier v = *(ushort*)sp; 23877dd7cddfSDavid du Colombier for(x=bx; x>ex; x--, ws++){ 23887dd7cddfSDavid du Colombier i = x&7; 23897dd7cddfSDavid du Colombier if(i == 8-1) 23907dd7cddfSDavid du Colombier bits = *q++; 23917dd7cddfSDavid du Colombier DBG print("bits %lux sh %d...", bits, i); 23927dd7cddfSDavid du Colombier if((bits>>i)&1) 23937dd7cddfSDavid du Colombier *ws = v; 23947dd7cddfSDavid du Colombier } 23957dd7cddfSDavid du Colombier break; 23967dd7cddfSDavid du Colombier case 24: 23977dd7cddfSDavid du Colombier wc = wp; 23987dd7cddfSDavid du Colombier for(x=bx; x>ex; x--, wc+=3){ 23997dd7cddfSDavid du Colombier i = x&7; 24007dd7cddfSDavid du Colombier if(i == 8-1) 24017dd7cddfSDavid du Colombier bits = *q++; 24027dd7cddfSDavid du Colombier DBG print("bits %lux sh %d...", bits, i); 24037dd7cddfSDavid du Colombier if((bits>>i)&1){ 24047dd7cddfSDavid du Colombier wc[0] = sp[0]; 24057dd7cddfSDavid du Colombier wc[1] = sp[1]; 24067dd7cddfSDavid du Colombier wc[2] = sp[2]; 24077dd7cddfSDavid du Colombier } 24087dd7cddfSDavid du Colombier } 24097dd7cddfSDavid du Colombier break; 24107dd7cddfSDavid du Colombier case 32: 24117dd7cddfSDavid du Colombier wl = (ulong*)wp; 24127dd7cddfSDavid du Colombier v = *(ulong*)sp; 24137dd7cddfSDavid du Colombier for(x=bx; x>ex; x--, wl++){ 24147dd7cddfSDavid du Colombier i = x&7; 24157dd7cddfSDavid du Colombier if(i == 8-1) 24167dd7cddfSDavid du Colombier bits = *q++; 24177dd7cddfSDavid du Colombier DBG iprint("bits %lux sh %d...", bits, i); 24187dd7cddfSDavid du Colombier if((bits>>i)&1) 24197dd7cddfSDavid du Colombier *wl = v; 24207dd7cddfSDavid du Colombier } 24217dd7cddfSDavid du Colombier break; 24227dd7cddfSDavid du Colombier } 24237dd7cddfSDavid du Colombier } 24247dd7cddfSDavid du Colombier 24257dd7cddfSDavid du Colombier DBG print("\n"); 24267dd7cddfSDavid du Colombier return 1; 24277dd7cddfSDavid du Colombier } 24287dd7cddfSDavid du Colombier #undef DBG 24297dd7cddfSDavid du Colombier 2430*8ccd4a63SDavid du Colombier 2431*8ccd4a63SDavid du Colombier /* 2432*8ccd4a63SDavid du Colombier * Fill entire byte with replicated (if necessary) copy of source pixel, 2433*8ccd4a63SDavid du Colombier * assuming destination ldepth is >= source ldepth. 2434*8ccd4a63SDavid du Colombier * 2435*8ccd4a63SDavid du Colombier * This code is just plain wrong for >8bpp. 2436*8ccd4a63SDavid du Colombier * 2437*8ccd4a63SDavid du Colombier ulong 2438*8ccd4a63SDavid du Colombier membyteval(Memimage *src) 2439*8ccd4a63SDavid du Colombier { 2440*8ccd4a63SDavid du Colombier int i, val, bpp; 2441*8ccd4a63SDavid du Colombier uchar uc; 2442*8ccd4a63SDavid du Colombier 2443*8ccd4a63SDavid du Colombier unloadmemimage(src, src->r, &uc, 1); 2444*8ccd4a63SDavid du Colombier bpp = src->depth; 2445*8ccd4a63SDavid du Colombier uc <<= (src->r.min.x&(7/src->depth))*src->depth; 2446*8ccd4a63SDavid du Colombier uc &= ~(0xFF>>bpp); 2447*8ccd4a63SDavid du Colombier // pixel value is now in high part of byte. repeat throughout byte 2448*8ccd4a63SDavid du Colombier val = uc; 2449*8ccd4a63SDavid du Colombier for(i=bpp; i<8; i<<=1) 2450*8ccd4a63SDavid du Colombier val |= val>>i; 2451*8ccd4a63SDavid du Colombier return val; 2452*8ccd4a63SDavid du Colombier } 2453*8ccd4a63SDavid du Colombier * 2454*8ccd4a63SDavid du Colombier */ 2455*8ccd4a63SDavid du Colombier 245659cc4ca5SDavid du Colombier void 245759cc4ca5SDavid du Colombier _memfillcolor(Memimage *i, ulong val) 245859cc4ca5SDavid du Colombier { 245959cc4ca5SDavid du Colombier ulong bits; 246059cc4ca5SDavid du Colombier int d, y; 2461*8ccd4a63SDavid du Colombier uchar p[4]; 246259cc4ca5SDavid du Colombier 246359cc4ca5SDavid du Colombier if(val == DNofill) 246459cc4ca5SDavid du Colombier return; 246559cc4ca5SDavid du Colombier 246659cc4ca5SDavid du Colombier bits = _rgbatoimg(i, val); 246759cc4ca5SDavid du Colombier switch(i->depth){ 246859cc4ca5SDavid du Colombier case 24: /* 24-bit images suck */ 246959cc4ca5SDavid du Colombier for(y=i->r.min.y; y<i->r.max.y; y++) 247059cc4ca5SDavid du Colombier memset24(byteaddr(i, Pt(i->r.min.x, y)), bits, Dx(i->r)); 247159cc4ca5SDavid du Colombier break; 247259cc4ca5SDavid du Colombier default: /* 1, 2, 4, 8, 16, 32 */ 247359cc4ca5SDavid du Colombier for(d=i->depth; d<32; d*=2) 247459cc4ca5SDavid du Colombier bits = (bits << d) | bits; 2475*8ccd4a63SDavid du Colombier p[0] = bits; /* make little endian */ 2476*8ccd4a63SDavid du Colombier p[1] = bits>>8; 2477*8ccd4a63SDavid du Colombier p[2] = bits>>16; 2478*8ccd4a63SDavid du Colombier p[3] = bits>>24; 2479*8ccd4a63SDavid du Colombier bits = *(ulong*)p; 248059cc4ca5SDavid du Colombier memsetl(wordaddr(i, i->r.min), bits, i->width*Dy(i->r)); 248159cc4ca5SDavid du Colombier break; 248259cc4ca5SDavid du Colombier } 248359cc4ca5SDavid du Colombier } 2484*8ccd4a63SDavid du Colombier 2485