18ccd4a63SDavid du Colombier #include <u.h>
28ccd4a63SDavid du Colombier #include <libc.h>
38ccd4a63SDavid du Colombier #include <draw.h>
48ccd4a63SDavid du Colombier #include <memdraw.h>
57dd7cddfSDavid du Colombier
68ccd4a63SDavid du Colombier int drawdebug;
78ccd4a63SDavid 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 /*
13*58da3067SDavid du Colombier * For 16-bit values, x / 255 == (t = x+1, (t+(t>>8)) >> 8).
14*58da3067SDavid du Colombier * We add another 127 to round to the nearest value rather
15*58da3067SDavid du Colombier * than truncate.
16*58da3067SDavid du Colombier *
17*58da3067SDavid du Colombier * CALCxy does x bytewise calculations on y input images (x=1,4; y=1,2).
18*58da3067SDavid du Colombier * CALC2x does two parallel 16-bit calculations on y input images (y=1,2).
197dd7cddfSDavid du Colombier */
20*58da3067SDavid du Colombier #define CALC11(a, v, tmp) \
21*58da3067SDavid du Colombier (tmp=(a)*(v)+128, (tmp+(tmp>>8))>>8)
227dd7cddfSDavid du Colombier
23*58da3067SDavid du Colombier #define CALC12(a1, v1, a2, v2, tmp) \
24*58da3067SDavid du Colombier (tmp=(a1)*(v1)+(a2)*(v2)+128, (tmp+(tmp>>8))>>8)
258ccd4a63SDavid du Colombier
26*58da3067SDavid du Colombier #define MASK 0xFF00FF
27*58da3067SDavid du Colombier
28*58da3067SDavid du Colombier #define CALC21(a, vvuu, tmp) \
29*58da3067SDavid du Colombier (tmp=(a)*(vvuu)+0x00800080, ((tmp+((tmp>>8)&MASK))>>8)&MASK)
30*58da3067SDavid du Colombier
31*58da3067SDavid du Colombier #define CALC41(a, rgba, tmp1, tmp2) \
32*58da3067SDavid du Colombier (CALC21(a, rgba & MASK, tmp1) | \
33*58da3067SDavid du Colombier (CALC21(a, (rgba>>8)&MASK, tmp2)<<8))
34*58da3067SDavid du Colombier
35*58da3067SDavid du Colombier #define CALC22(a1, vvuu1, a2, vvuu2, tmp) \
36*58da3067SDavid du Colombier (tmp=(a1)*(vvuu1)+(a2)*(vvuu2)+0x00800080, ((tmp+((tmp>>8)&MASK))>>8)&MASK)
37*58da3067SDavid du Colombier
38*58da3067SDavid du Colombier #define CALC42(a1, rgba1, a2, rgba2, tmp1, tmp2) \
39*58da3067SDavid du Colombier (CALC22(a1, rgba1 & MASK, a2, rgba2 & MASK, tmp1) | \
40*58da3067SDavid du Colombier (CALC22(a1, (rgba1>>8) & MASK, a2, (rgba2>>8) & MASK, tmp2)<<8))
418ccd4a63SDavid du Colombier
427dd7cddfSDavid du Colombier static void mktables(void);
437dd7cddfSDavid du Colombier typedef int Subdraw(Memdrawparam*);
447dd7cddfSDavid du Colombier static Subdraw chardraw, alphadraw, memoptdraw;
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier static Memimage* memones;
477dd7cddfSDavid du Colombier static Memimage* memzeros;
487dd7cddfSDavid du Colombier Memimage *memwhite;
497dd7cddfSDavid du Colombier Memimage *memblack;
507dd7cddfSDavid du Colombier Memimage *memtransparent;
517dd7cddfSDavid du Colombier Memimage *memopaque;
527dd7cddfSDavid du Colombier
538ccd4a63SDavid du Colombier int _ifmt(Fmt*);
547dd7cddfSDavid du Colombier
557dd7cddfSDavid du Colombier void
_memimageinit(void)567dd7cddfSDavid du Colombier _memimageinit(void)
577dd7cddfSDavid du Colombier {
587dd7cddfSDavid du Colombier static int didinit = 0;
597dd7cddfSDavid du Colombier
607dd7cddfSDavid du Colombier if(didinit)
617dd7cddfSDavid du Colombier return;
627dd7cddfSDavid du Colombier
637dd7cddfSDavid du Colombier didinit = 1;
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier mktables();
668ccd4a63SDavid du Colombier _memmkcmap();
678ccd4a63SDavid du Colombier
688ccd4a63SDavid du Colombier fmtinstall('R', Rfmt);
698ccd4a63SDavid du Colombier fmtinstall('P', Pfmt);
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier memones = allocmemimage(Rect(0,0,1,1), GREY1);
727dd7cddfSDavid du Colombier memones->flags |= Frepl;
737dd7cddfSDavid du Colombier memones->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
747dd7cddfSDavid du Colombier *byteaddr(memones, ZP) = ~0;
757dd7cddfSDavid du Colombier
767dd7cddfSDavid du Colombier memzeros = allocmemimage(Rect(0,0,1,1), GREY1);
777dd7cddfSDavid du Colombier memzeros->flags |= Frepl;
787dd7cddfSDavid du Colombier memzeros->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
797dd7cddfSDavid du Colombier *byteaddr(memzeros, ZP) = 0;
807dd7cddfSDavid du Colombier
817dd7cddfSDavid du Colombier if(memones == nil || memzeros == nil)
827dd7cddfSDavid du Colombier assert(0 /*cannot initialize memimage library */); /* RSC BUG */
837dd7cddfSDavid du Colombier
847dd7cddfSDavid du Colombier memwhite = memones;
857dd7cddfSDavid du Colombier memblack = memzeros;
867dd7cddfSDavid du Colombier memopaque = memones;
877dd7cddfSDavid du Colombier memtransparent = memzeros;
887dd7cddfSDavid du Colombier }
897dd7cddfSDavid du Colombier
908ccd4a63SDavid du Colombier ulong _imgtorgba(Memimage*, ulong);
918ccd4a63SDavid du Colombier ulong _rgbatoimg(Memimage*, ulong);
928ccd4a63SDavid du Colombier ulong _pixelbits(Memimage*, Point);
937dd7cddfSDavid du Colombier
947dd7cddfSDavid du Colombier #define DBG if(0)
958ccd4a63SDavid du Colombier static Memdrawparam par;
968ccd4a63SDavid du Colombier
977dd7cddfSDavid du Colombier Memdrawparam*
_memimagedrawsetup(Memimage * dst,Rectangle r,Memimage * src,Point p0,Memimage * mask,Point p1,int op)988ccd4a63SDavid du Colombier _memimagedrawsetup(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op)
997dd7cddfSDavid du Colombier {
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier if(mask == nil)
1027dd7cddfSDavid du Colombier mask = memopaque;
1037dd7cddfSDavid du Colombier
1048ccd4a63SDavid 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);
1057dd7cddfSDavid du Colombier
1067dd7cddfSDavid du Colombier if(drawclip(dst, &r, src, &p0, mask, &p1, &par.sr, &par.mr) == 0){
1078ccd4a63SDavid du Colombier // if(drawdebug)
1088ccd4a63SDavid du Colombier // iprint("empty clipped rectangle\n");
1097dd7cddfSDavid du Colombier return nil;
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier
1128ccd4a63SDavid du Colombier if(op < Clear || op > SoverD){
1138ccd4a63SDavid du Colombier // if(drawdebug)
1148ccd4a63SDavid du Colombier // iprint("op out of range: %d\n", op);
1158ccd4a63SDavid du Colombier return nil;
1168ccd4a63SDavid du Colombier }
1178ccd4a63SDavid du Colombier
1188ccd4a63SDavid du Colombier par.op = op;
1197dd7cddfSDavid du Colombier par.dst = dst;
1207dd7cddfSDavid du Colombier par.r = r;
1217dd7cddfSDavid du Colombier par.src = src;
1227dd7cddfSDavid du Colombier /* par.sr set by drawclip */
1237dd7cddfSDavid du Colombier par.mask = mask;
1247dd7cddfSDavid du Colombier /* par.mr set by drawclip */
1257dd7cddfSDavid du Colombier
1267dd7cddfSDavid du Colombier par.state = 0;
1277dd7cddfSDavid du Colombier if(src->flags&Frepl){
1287dd7cddfSDavid du Colombier par.state |= Replsrc;
1297dd7cddfSDavid du Colombier if(Dx(src->r)==1 && Dy(src->r)==1){
1308ccd4a63SDavid du Colombier par.sval = _pixelbits(src, src->r.min);
1317dd7cddfSDavid du Colombier par.state |= Simplesrc;
1327dd7cddfSDavid du Colombier par.srgba = _imgtorgba(src, par.sval);
1337dd7cddfSDavid du Colombier par.sdval = _rgbatoimg(dst, par.srgba);
1348ccd4a63SDavid du Colombier if((par.srgba&0xFF) == 0 && (op&DoutS)){
1358ccd4a63SDavid du Colombier // if (drawdebug) iprint("fill with transparent source\n");
1368ccd4a63SDavid du Colombier return nil; /* no-op successfully handled */
1378ccd4a63SDavid du Colombier }
1387dd7cddfSDavid du Colombier }
1397dd7cddfSDavid du Colombier }
1407dd7cddfSDavid du Colombier
1417dd7cddfSDavid du Colombier if(mask->flags & Frepl){
1427dd7cddfSDavid du Colombier par.state |= Replmask;
1437dd7cddfSDavid du Colombier if(Dx(mask->r)==1 && Dy(mask->r)==1){
1448ccd4a63SDavid du Colombier par.mval = _pixelbits(mask, mask->r.min);
1458ccd4a63SDavid du Colombier if(par.mval == 0 && (op&DoutS)){
1468ccd4a63SDavid du Colombier // if(drawdebug) iprint("fill with zero mask\n");
1477dd7cddfSDavid du Colombier return nil; /* no-op successfully handled */
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier par.state |= Simplemask;
1507dd7cddfSDavid du Colombier if(par.mval == ~0)
1517dd7cddfSDavid du Colombier par.state |= Fullmask;
1527dd7cddfSDavid du Colombier par.mrgba = _imgtorgba(mask, par.mval);
1537dd7cddfSDavid du Colombier }
1547dd7cddfSDavid du Colombier }
1557dd7cddfSDavid du Colombier
1568ccd4a63SDavid du Colombier // if(drawdebug)
1578ccd4a63SDavid du Colombier // iprint("dr %R sr %R mr %R...", r, par.sr, par.mr);
1588ccd4a63SDavid du Colombier DBG print("draw dr %R sr %R mr %R %lux\n", r, par.sr, par.mr, par.state);
1597dd7cddfSDavid du Colombier
1607dd7cddfSDavid du Colombier return ∥
1617dd7cddfSDavid du Colombier }
1627dd7cddfSDavid du Colombier
1637dd7cddfSDavid du Colombier void
_memimagedraw(Memdrawparam * par)1647dd7cddfSDavid du Colombier _memimagedraw(Memdrawparam *par)
1657dd7cddfSDavid du Colombier {
1667dd7cddfSDavid du Colombier if (par == nil)
1677dd7cddfSDavid du Colombier return;
1687dd7cddfSDavid du Colombier
1697dd7cddfSDavid du Colombier /*
1707dd7cddfSDavid du Colombier * Now that we've clipped the parameters down to be consistent, we
1717dd7cddfSDavid du Colombier * simply try sub-drawing routines in order until we find one that was able
1727dd7cddfSDavid du Colombier * to handle us. If the sub-drawing routine returns zero, it means it was
1737dd7cddfSDavid du Colombier * unable to satisfy the request, so we do not return.
1747dd7cddfSDavid du Colombier */
1757dd7cddfSDavid du Colombier
1767dd7cddfSDavid du Colombier /*
1777dd7cddfSDavid du Colombier * Hardware support. Each video driver provides this function,
1787dd7cddfSDavid du Colombier * which checks to see if there is anything it can help with.
1797dd7cddfSDavid du Colombier * There could be an if around this checking to see if dst is in video memory.
1807dd7cddfSDavid du Colombier */
1818ccd4a63SDavid du Colombier DBG print("test hwdraw\n");
1828ccd4a63SDavid du Colombier if(hwdraw(par)){
1838ccd4a63SDavid du Colombier //if(drawdebug) iprint("hw handled\n");
1848ccd4a63SDavid du Colombier DBG print("hwdraw handled\n");
1857dd7cddfSDavid du Colombier return;
1867dd7cddfSDavid du Colombier }
1877dd7cddfSDavid du Colombier /*
1887dd7cddfSDavid du Colombier * Optimizations using memmove and memset.
1897dd7cddfSDavid du Colombier */
1908ccd4a63SDavid du Colombier DBG print("test memoptdraw\n");
1917dd7cddfSDavid du Colombier if(memoptdraw(par)){
1928ccd4a63SDavid du Colombier //if(drawdebug) iprint("memopt handled\n");
1938ccd4a63SDavid du Colombier DBG print("memopt handled\n");
1947dd7cddfSDavid du Colombier return;
1957dd7cddfSDavid du Colombier }
1967dd7cddfSDavid du Colombier
1977dd7cddfSDavid du Colombier /*
1987dd7cddfSDavid du Colombier * Character drawing.
1997dd7cddfSDavid du Colombier * Solid source color being painted through a boolean mask onto a high res image.
2007dd7cddfSDavid du Colombier */
2018ccd4a63SDavid du Colombier DBG print("test chardraw\n");
2027dd7cddfSDavid du Colombier if(chardraw(par)){
2038ccd4a63SDavid du Colombier //if(drawdebug) iprint("chardraw handled\n");
2048ccd4a63SDavid du Colombier DBG print("chardraw handled\n");
2057dd7cddfSDavid du Colombier return;
2067dd7cddfSDavid du Colombier }
2077dd7cddfSDavid du Colombier
2087dd7cddfSDavid du Colombier /*
2097dd7cddfSDavid du Colombier * General calculation-laden case that does alpha for each pixel.
2107dd7cddfSDavid du Colombier */
2118ccd4a63SDavid du Colombier DBG print("do alphadraw\n");
2127dd7cddfSDavid du Colombier alphadraw(par);
2138ccd4a63SDavid du Colombier //if(drawdebug) iprint("alphadraw handled\n");
2148ccd4a63SDavid du Colombier DBG print("alphadraw handled\n");
2157dd7cddfSDavid du Colombier }
2167dd7cddfSDavid du Colombier #undef DBG
2177dd7cddfSDavid du Colombier
2187dd7cddfSDavid du Colombier /*
2197dd7cddfSDavid du Colombier * Clip the destination rectangle further based on the properties of the
2207dd7cddfSDavid du Colombier * source and mask rectangles. Once the destination rectangle is properly
2217dd7cddfSDavid du Colombier * clipped, adjust the source and mask rectangles to be the same size.
2227dd7cddfSDavid du Colombier * Then if source or mask is replicated, move its clipped rectangle
2237dd7cddfSDavid du Colombier * so that its minimum point falls within the repl rectangle.
2247dd7cddfSDavid du Colombier *
2257dd7cddfSDavid du Colombier * Return zero if the final rectangle is null.
2267dd7cddfSDavid du Colombier */
2277dd7cddfSDavid du Colombier int
drawclip(Memimage * dst,Rectangle * r,Memimage * src,Point * p0,Memimage * mask,Point * p1,Rectangle * sr,Rectangle * mr)2287dd7cddfSDavid du Colombier drawclip(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask, Point *p1, Rectangle *sr, Rectangle *mr)
2297dd7cddfSDavid du Colombier {
2307dd7cddfSDavid du Colombier Point rmin, delta;
2317dd7cddfSDavid du Colombier int splitcoords;
2327dd7cddfSDavid du Colombier Rectangle omr;
2337dd7cddfSDavid du Colombier
2347dd7cddfSDavid du Colombier if(r->min.x>=r->max.x || r->min.y>=r->max.y)
2357dd7cddfSDavid du Colombier return 0;
2367dd7cddfSDavid du Colombier splitcoords = (p0->x!=p1->x) || (p0->y!=p1->y);
2377dd7cddfSDavid du Colombier /* clip to destination */
2387dd7cddfSDavid du Colombier rmin = r->min;
2397dd7cddfSDavid du Colombier if(!rectclip(r, dst->r) || !rectclip(r, dst->clipr))
2407dd7cddfSDavid du Colombier return 0;
2417dd7cddfSDavid du Colombier /* move mask point */
2427dd7cddfSDavid du Colombier p1->x += r->min.x-rmin.x;
2437dd7cddfSDavid du Colombier p1->y += r->min.y-rmin.y;
2447dd7cddfSDavid du Colombier /* move source point */
2457dd7cddfSDavid du Colombier p0->x += r->min.x-rmin.x;
2467dd7cddfSDavid du Colombier p0->y += r->min.y-rmin.y;
2477dd7cddfSDavid du Colombier /* map destination rectangle into source */
2487dd7cddfSDavid du Colombier sr->min = *p0;
2497dd7cddfSDavid du Colombier sr->max.x = p0->x+Dx(*r);
2507dd7cddfSDavid du Colombier sr->max.y = p0->y+Dy(*r);
2517dd7cddfSDavid du Colombier /* sr is r in source coordinates; clip to source */
2527dd7cddfSDavid du Colombier if(!(src->flags&Frepl) && !rectclip(sr, src->r))
2537dd7cddfSDavid du Colombier return 0;
2547dd7cddfSDavid du Colombier if(!rectclip(sr, src->clipr))
2557dd7cddfSDavid du Colombier return 0;
2567dd7cddfSDavid du Colombier /* compute and clip rectangle in mask */
2577dd7cddfSDavid du Colombier if(splitcoords){
2587dd7cddfSDavid du Colombier /* move mask point with source */
2597dd7cddfSDavid du Colombier p1->x += sr->min.x-p0->x;
2607dd7cddfSDavid du Colombier p1->y += sr->min.y-p0->y;
2617dd7cddfSDavid du Colombier mr->min = *p1;
2627dd7cddfSDavid du Colombier mr->max.x = p1->x+Dx(*sr);
2637dd7cddfSDavid du Colombier mr->max.y = p1->y+Dy(*sr);
2647dd7cddfSDavid du Colombier omr = *mr;
2657dd7cddfSDavid du Colombier /* mr is now rectangle in mask; clip it */
2667dd7cddfSDavid du Colombier if(!(mask->flags&Frepl) && !rectclip(mr, mask->r))
2677dd7cddfSDavid du Colombier return 0;
2687dd7cddfSDavid du Colombier if(!rectclip(mr, mask->clipr))
2697dd7cddfSDavid du Colombier return 0;
2707dd7cddfSDavid du Colombier /* reflect any clips back to source */
2717dd7cddfSDavid du Colombier sr->min.x += mr->min.x-omr.min.x;
2727dd7cddfSDavid du Colombier sr->min.y += mr->min.y-omr.min.y;
2737dd7cddfSDavid du Colombier sr->max.x += mr->max.x-omr.max.x;
2747dd7cddfSDavid du Colombier sr->max.y += mr->max.y-omr.max.y;
2757dd7cddfSDavid du Colombier *p1 = mr->min;
2767dd7cddfSDavid du Colombier }else{
2777dd7cddfSDavid du Colombier if(!(mask->flags&Frepl) && !rectclip(sr, mask->r))
2787dd7cddfSDavid du Colombier return 0;
2797dd7cddfSDavid du Colombier if(!rectclip(sr, mask->clipr))
2807dd7cddfSDavid du Colombier return 0;
2817dd7cddfSDavid du Colombier *p1 = sr->min;
2827dd7cddfSDavid du Colombier }
2837dd7cddfSDavid du Colombier
2847dd7cddfSDavid du Colombier /* move source clipping back to destination */
2857dd7cddfSDavid du Colombier delta.x = r->min.x - p0->x;
2867dd7cddfSDavid du Colombier delta.y = r->min.y - p0->y;
2877dd7cddfSDavid du Colombier r->min.x = sr->min.x + delta.x;
2887dd7cddfSDavid du Colombier r->min.y = sr->min.y + delta.y;
2897dd7cddfSDavid du Colombier r->max.x = sr->max.x + delta.x;
2907dd7cddfSDavid du Colombier r->max.y = sr->max.y + delta.y;
2917dd7cddfSDavid du Colombier
2927dd7cddfSDavid du Colombier /* move source rectangle so sr->min is in src->r */
2937dd7cddfSDavid du Colombier if(src->flags&Frepl) {
2947dd7cddfSDavid du Colombier delta.x = drawreplxy(src->r.min.x, src->r.max.x, sr->min.x) - sr->min.x;
2957dd7cddfSDavid du Colombier delta.y = drawreplxy(src->r.min.y, src->r.max.y, sr->min.y) - sr->min.y;
2967dd7cddfSDavid du Colombier sr->min.x += delta.x;
2977dd7cddfSDavid du Colombier sr->min.y += delta.y;
2987dd7cddfSDavid du Colombier sr->max.x += delta.x;
2997dd7cddfSDavid du Colombier sr->max.y += delta.y;
3007dd7cddfSDavid du Colombier }
3017dd7cddfSDavid du Colombier *p0 = sr->min;
3027dd7cddfSDavid du Colombier
3037dd7cddfSDavid du Colombier /* move mask point so it is in mask->r */
3048ccd4a63SDavid du Colombier *p1 = drawrepl(mask->r, *p1);
3057dd7cddfSDavid du Colombier mr->min = *p1;
3067dd7cddfSDavid du Colombier mr->max.x = p1->x+Dx(*sr);
3077dd7cddfSDavid du Colombier mr->max.y = p1->y+Dy(*sr);
3087dd7cddfSDavid du Colombier
3097dd7cddfSDavid du Colombier assert(Dx(*sr) == Dx(*mr) && Dx(*mr) == Dx(*r));
3107dd7cddfSDavid du Colombier assert(Dy(*sr) == Dy(*mr) && Dy(*mr) == Dy(*r));
3118ccd4a63SDavid du Colombier assert(ptinrect(*p0, src->r));
3128ccd4a63SDavid du Colombier assert(ptinrect(*p1, mask->r));
3138ccd4a63SDavid du Colombier assert(ptinrect(r->min, dst->r));
3147dd7cddfSDavid du Colombier
3157dd7cddfSDavid du Colombier return 1;
3167dd7cddfSDavid du Colombier }
3177dd7cddfSDavid du Colombier
3187dd7cddfSDavid du Colombier /*
3197dd7cddfSDavid du Colombier * Conversion tables.
3207dd7cddfSDavid du Colombier */
3217dd7cddfSDavid du Colombier static uchar replbit[1+8][256]; /* replbit[x][y] is the replication of the x-bit quantity y to 8-bit depth */
322*58da3067SDavid du Colombier static uchar conv18[256][8]; /* conv18[x][y] is the yth pixel in the depth-1 pixel x */
323*58da3067SDavid du Colombier static uchar conv28[256][4]; /* ... */
324*58da3067SDavid du Colombier static uchar conv48[256][2];
3257dd7cddfSDavid du Colombier
3267dd7cddfSDavid du Colombier /*
3277dd7cddfSDavid du Colombier * bitmap of how to replicate n bits to fill 8, for 1 ≤ n ≤ 8.
3287dd7cddfSDavid du Colombier * the X's are where to put the bottom (ones) bit of the n-bit pattern.
3297dd7cddfSDavid du Colombier * only the top 8 bits of the result are actually used.
3307dd7cddfSDavid du Colombier * (the lower 8 bits are needed to get bits in the right place
3317dd7cddfSDavid du Colombier * when n is not a divisor of 8.)
3327dd7cddfSDavid du Colombier *
3337dd7cddfSDavid du Colombier * Should check to see if its easier to just refer to replmul than
3347dd7cddfSDavid du Colombier * use the precomputed values in replbit. On PCs it may well
3357dd7cddfSDavid du Colombier * be; on machines with slow multiply instructions it probably isn't.
3367dd7cddfSDavid du Colombier */
3377dd7cddfSDavid du Colombier #define a ((((((((((((((((0
3387dd7cddfSDavid du Colombier #define X *2+1)
3397dd7cddfSDavid du Colombier #define _ *2)
3407dd7cddfSDavid du Colombier static int replmul[1+8] = {
3417dd7cddfSDavid du Colombier 0,
3427dd7cddfSDavid du Colombier a X X X X X X X X X X X X X X X X,
3437dd7cddfSDavid du Colombier a _ X _ X _ X _ X _ X _ X _ X _ X,
3447dd7cddfSDavid du Colombier a _ _ X _ _ X _ _ X _ _ X _ _ X _,
3457dd7cddfSDavid du Colombier a _ _ _ X _ _ _ X _ _ _ X _ _ _ X,
3467dd7cddfSDavid du Colombier a _ _ _ _ X _ _ _ _ X _ _ _ _ X _,
3477dd7cddfSDavid du Colombier a _ _ _ _ _ X _ _ _ _ _ X _ _ _ _,
3487dd7cddfSDavid du Colombier a _ _ _ _ _ _ X _ _ _ _ _ _ X _ _,
3497dd7cddfSDavid du Colombier a _ _ _ _ _ _ _ X _ _ _ _ _ _ _ X,
3507dd7cddfSDavid du Colombier };
3517dd7cddfSDavid du Colombier #undef a
3527dd7cddfSDavid du Colombier #undef X
3537dd7cddfSDavid du Colombier #undef _
3547dd7cddfSDavid du Colombier
3557dd7cddfSDavid du Colombier static void
mktables(void)3567dd7cddfSDavid du Colombier mktables(void)
3577dd7cddfSDavid du Colombier {
358*58da3067SDavid du Colombier int i, j, mask, sh, small;
3597dd7cddfSDavid du Colombier
3607dd7cddfSDavid du Colombier if(tablesbuilt)
3617dd7cddfSDavid du Colombier return;
3627dd7cddfSDavid du Colombier
3638ccd4a63SDavid du Colombier fmtinstall('R', Rfmt);
3648ccd4a63SDavid du Colombier fmtinstall('P', Pfmt);
3657dd7cddfSDavid du Colombier tablesbuilt = 1;
3668ccd4a63SDavid du Colombier
3677dd7cddfSDavid du Colombier /* bit replication up to 8 bits */
3687dd7cddfSDavid du Colombier for(i=0; i<256; i++){
3697dd7cddfSDavid du Colombier for(j=0; j<=8; j++){ /* j <= 8 [sic] */
3707dd7cddfSDavid du Colombier small = i & ((1<<j)-1);
3717dd7cddfSDavid du Colombier replbit[j][i] = (small*replmul[j])>>8;
3727dd7cddfSDavid du Colombier }
3737dd7cddfSDavid du Colombier }
3747dd7cddfSDavid du Colombier
375*58da3067SDavid du Colombier /* bit unpacking up to 8 bits, only powers of 2 */
376*58da3067SDavid du Colombier for(i=0; i<256; i++){
377*58da3067SDavid du Colombier for(j=0, sh=7, mask=1; j<8; j++, sh--)
378*58da3067SDavid du Colombier conv18[i][j] = replbit[1][(i>>sh)&mask];
379*58da3067SDavid du Colombier
380*58da3067SDavid du Colombier for(j=0, sh=6, mask=3; j<4; j++, sh-=2)
381*58da3067SDavid du Colombier conv28[i][j] = replbit[2][(i>>sh)&mask];
382*58da3067SDavid du Colombier
383*58da3067SDavid du Colombier for(j=0, sh=4, mask=15; j<2; j++, sh-=4)
384*58da3067SDavid du Colombier conv48[i][j] = replbit[4][(i>>sh)&mask];
385*58da3067SDavid du Colombier }
3867dd7cddfSDavid du Colombier }
3878ccd4a63SDavid du Colombier
3888ccd4a63SDavid du Colombier static uchar ones = 0xff;
3897dd7cddfSDavid du Colombier
3907dd7cddfSDavid du Colombier /*
3917dd7cddfSDavid du Colombier * General alpha drawing case. Can handle anything.
3927dd7cddfSDavid du Colombier */
3937dd7cddfSDavid du Colombier typedef struct Buffer Buffer;
3947dd7cddfSDavid du Colombier struct Buffer {
3958ccd4a63SDavid du Colombier /* used by most routines */
3967dd7cddfSDavid du Colombier uchar *red;
3977dd7cddfSDavid du Colombier uchar *grn;
3987dd7cddfSDavid du Colombier uchar *blu;
3997dd7cddfSDavid du Colombier uchar *alpha;
4007dd7cddfSDavid du Colombier uchar *grey;
4018ccd4a63SDavid du Colombier ulong *rgba;
4027dd7cddfSDavid du Colombier int delta; /* number of bytes to add to pointer to get next pixel to the right */
4038ccd4a63SDavid du Colombier
4048ccd4a63SDavid du Colombier /* used by boolcalc* for mask data */
4057dd7cddfSDavid du Colombier uchar *m; /* ptr to mask data r.min byte; like p->bytermin */
4067dd7cddfSDavid du Colombier int mskip; /* no. of left bits to skip in *m */
4077dd7cddfSDavid du Colombier uchar *bm; /* ptr to mask data img->r.min byte; like p->bytey0s */
4087dd7cddfSDavid du Colombier int bmskip; /* no. of left bits to skip in *bm */
4097dd7cddfSDavid du Colombier uchar *em; /* ptr to mask data img->r.max.x byte; like p->bytey0e */
4107dd7cddfSDavid du Colombier int emskip; /* no. of right bits to skip in *em */
4117dd7cddfSDavid du Colombier };
4127dd7cddfSDavid du Colombier
4137dd7cddfSDavid du Colombier typedef struct Param Param;
4148ccd4a63SDavid du Colombier typedef Buffer Readfn(Param*, uchar*, int);
4158ccd4a63SDavid du Colombier typedef void Writefn(Param*, uchar*, Buffer);
4168ccd4a63SDavid du Colombier typedef Buffer Calcfn(Buffer, Buffer, Buffer, int, int, int);
4177dd7cddfSDavid du Colombier
4187dd7cddfSDavid du Colombier enum {
4197dd7cddfSDavid du Colombier MAXBCACHE = 16
4207dd7cddfSDavid du Colombier };
4217dd7cddfSDavid du Colombier
4227dd7cddfSDavid du Colombier /* giant rathole to customize functions with */
4237dd7cddfSDavid du Colombier struct Param {
4247dd7cddfSDavid du Colombier Readfn *replcall;
4257dd7cddfSDavid du Colombier Readfn *greymaskcall;
4267dd7cddfSDavid du Colombier Readfn *convreadcall;
4277dd7cddfSDavid du Colombier Writefn *convwritecall;
4287dd7cddfSDavid du Colombier
4297dd7cddfSDavid du Colombier Memimage *img;
4307dd7cddfSDavid du Colombier Rectangle r;
4317dd7cddfSDavid du Colombier int dx; /* of r */
4327dd7cddfSDavid du Colombier int needbuf;
4337dd7cddfSDavid du Colombier int convgrey;
4347dd7cddfSDavid du Colombier int alphaonly;
4357dd7cddfSDavid du Colombier
4367dd7cddfSDavid du Colombier uchar *bytey0s; /* byteaddr(Pt(img->r.min.x, img->r.min.y)) */
4377dd7cddfSDavid du Colombier uchar *bytermin; /* byteaddr(Pt(r.min.x, img->r.min.y)) */
4387dd7cddfSDavid du Colombier uchar *bytey0e; /* byteaddr(Pt(img->r.max.x, img->r.min.y)) */
4397dd7cddfSDavid du Colombier int bwidth;
4407dd7cddfSDavid du Colombier
4417dd7cddfSDavid du Colombier int replcache; /* if set, cache buffers */
4427dd7cddfSDavid du Colombier Buffer bcache[MAXBCACHE];
4437dd7cddfSDavid du Colombier ulong bfilled;
4447dd7cddfSDavid du Colombier uchar *bufbase;
4457dd7cddfSDavid du Colombier int bufoff;
4467dd7cddfSDavid du Colombier int bufdelta;
4477dd7cddfSDavid du Colombier
4487dd7cddfSDavid du Colombier int dir;
4497dd7cddfSDavid du Colombier
4507dd7cddfSDavid du Colombier int convbufoff;
4517dd7cddfSDavid du Colombier uchar *convbuf;
4527dd7cddfSDavid du Colombier Param *convdpar;
4537dd7cddfSDavid du Colombier int convdx;
4547dd7cddfSDavid du Colombier };
4557dd7cddfSDavid du Colombier
4567dd7cddfSDavid du Colombier static uchar *drawbuf;
4577dd7cddfSDavid du Colombier static int ndrawbuf;
4587dd7cddfSDavid du Colombier static int mdrawbuf;
4597dd7cddfSDavid du Colombier static Param spar, mpar, dpar; /* easier on the stacks */
4607dd7cddfSDavid du Colombier static Readfn greymaskread, replread, readptr;
4617dd7cddfSDavid du Colombier static Writefn nullwrite;
4628ccd4a63SDavid du Colombier static Calcfn alphacalc0, alphacalc14, alphacalc2810, alphacalc3679, alphacalc5, alphacalc11, alphacalcS;
4638ccd4a63SDavid du Colombier static Calcfn boolcalc14, boolcalc236789, boolcalc1011;
4647dd7cddfSDavid du Colombier
4657dd7cddfSDavid du Colombier static Readfn* readfn(Memimage*);
4667dd7cddfSDavid du Colombier static Readfn* readalphafn(Memimage*);
4677dd7cddfSDavid du Colombier static Writefn* writefn(Memimage*);
4687dd7cddfSDavid du Colombier
4697dd7cddfSDavid du Colombier static Calcfn* boolcopyfn(Memimage*, Memimage*);
4708ccd4a63SDavid du Colombier static Readfn* convfn(Memimage*, Param*, Memimage*, Param*);
4718ccd4a63SDavid du Colombier
4728ccd4a63SDavid du Colombier static Calcfn *alphacalc[Ncomp] =
4738ccd4a63SDavid du Colombier {
4748ccd4a63SDavid du Colombier alphacalc0, /* Clear */
4758ccd4a63SDavid du Colombier alphacalc14, /* DoutS */
4768ccd4a63SDavid du Colombier alphacalc2810, /* SoutD */
4778ccd4a63SDavid du Colombier alphacalc3679, /* DxorS */
4788ccd4a63SDavid du Colombier alphacalc14, /* DinS */
4798ccd4a63SDavid du Colombier alphacalc5, /* D */
4808ccd4a63SDavid du Colombier alphacalc3679, /* DatopS */
4818ccd4a63SDavid du Colombier alphacalc3679, /* DoverS */
4828ccd4a63SDavid du Colombier alphacalc2810, /* SinD */
4838ccd4a63SDavid du Colombier alphacalc3679, /* SatopD */
4848ccd4a63SDavid du Colombier alphacalc2810, /* S */
4858ccd4a63SDavid du Colombier alphacalc11, /* SoverD */
4868ccd4a63SDavid du Colombier };
4878ccd4a63SDavid du Colombier
4888ccd4a63SDavid du Colombier static Calcfn *boolcalc[Ncomp] =
4898ccd4a63SDavid du Colombier {
4908ccd4a63SDavid du Colombier alphacalc0, /* Clear */
4918ccd4a63SDavid du Colombier boolcalc14, /* DoutS */
4928ccd4a63SDavid du Colombier boolcalc236789, /* SoutD */
4938ccd4a63SDavid du Colombier boolcalc236789, /* DxorS */
4948ccd4a63SDavid du Colombier boolcalc14, /* DinS */
4958ccd4a63SDavid du Colombier alphacalc5, /* D */
4968ccd4a63SDavid du Colombier boolcalc236789, /* DatopS */
4978ccd4a63SDavid du Colombier boolcalc236789, /* DoverS */
4988ccd4a63SDavid du Colombier boolcalc236789, /* SinD */
4998ccd4a63SDavid du Colombier boolcalc236789, /* SatopD */
5008ccd4a63SDavid du Colombier boolcalc1011, /* S */
5018ccd4a63SDavid du Colombier boolcalc1011, /* SoverD */
5028ccd4a63SDavid du Colombier };
5037dd7cddfSDavid du Colombier
5047dd7cddfSDavid du Colombier static int
allocdrawbuf(void)5057dd7cddfSDavid du Colombier allocdrawbuf(void)
5067dd7cddfSDavid du Colombier {
5077dd7cddfSDavid du Colombier uchar *p;
5087dd7cddfSDavid du Colombier
5097dd7cddfSDavid du Colombier if(ndrawbuf > mdrawbuf){
5107dd7cddfSDavid du Colombier p = realloc(drawbuf, ndrawbuf);
5117dd7cddfSDavid du Colombier if(p == nil){
5127dd7cddfSDavid du Colombier werrstr("memimagedraw out of memory");
5137dd7cddfSDavid du Colombier return -1;
5147dd7cddfSDavid du Colombier }
5157dd7cddfSDavid du Colombier drawbuf = p;
5167dd7cddfSDavid du Colombier mdrawbuf = ndrawbuf;
5177dd7cddfSDavid du Colombier }
5187dd7cddfSDavid du Colombier return 0;
5197dd7cddfSDavid du Colombier }
5207dd7cddfSDavid du Colombier
5217dd7cddfSDavid du Colombier static Param
getparam(Memimage * img,Rectangle r,int convgrey,int needbuf)5227dd7cddfSDavid du Colombier getparam(Memimage *img, Rectangle r, int convgrey, int needbuf)
5237dd7cddfSDavid du Colombier {
5247dd7cddfSDavid du Colombier Param p;
5257dd7cddfSDavid du Colombier int nbuf;
5267dd7cddfSDavid du Colombier
5277dd7cddfSDavid du Colombier memset(&p, 0, sizeof p);
5287dd7cddfSDavid du Colombier
5297dd7cddfSDavid du Colombier p.img = img;
5307dd7cddfSDavid du Colombier p.r = r;
5317dd7cddfSDavid du Colombier p.dx = Dx(r);
5327dd7cddfSDavid du Colombier p.needbuf = needbuf;
5337dd7cddfSDavid du Colombier p.convgrey = convgrey;
5347dd7cddfSDavid du Colombier
5357dd7cddfSDavid du Colombier assert(img->r.min.x <= r.min.x && r.min.x < img->r.max.x);
5367dd7cddfSDavid du Colombier
5377dd7cddfSDavid du Colombier p.bytey0s = byteaddr(img, Pt(img->r.min.x, img->r.min.y));
5387dd7cddfSDavid du Colombier p.bytermin = byteaddr(img, Pt(r.min.x, img->r.min.y));
5397dd7cddfSDavid du Colombier p.bytey0e = byteaddr(img, Pt(img->r.max.x, img->r.min.y));
5407dd7cddfSDavid du Colombier p.bwidth = sizeof(ulong)*img->width;
5417dd7cddfSDavid du Colombier
5427dd7cddfSDavid du Colombier assert(p.bytey0s <= p.bytermin && p.bytermin <= p.bytey0e);
5437dd7cddfSDavid du Colombier
5447dd7cddfSDavid du Colombier if(p.r.min.x == p.img->r.min.x)
5457dd7cddfSDavid du Colombier assert(p.bytermin == p.bytey0s);
5467dd7cddfSDavid du Colombier
5477dd7cddfSDavid du Colombier nbuf = 1;
5487dd7cddfSDavid du Colombier if((img->flags&Frepl) && Dy(img->r) <= MAXBCACHE && Dy(img->r) < Dy(r)){
5497dd7cddfSDavid du Colombier p.replcache = 1;
5507dd7cddfSDavid du Colombier nbuf = Dy(img->r);
5517dd7cddfSDavid du Colombier }
5527dd7cddfSDavid du Colombier p.bufdelta = 4*p.dx;
5537dd7cddfSDavid du Colombier p.bufoff = ndrawbuf;
5547dd7cddfSDavid du Colombier ndrawbuf += p.bufdelta*nbuf;
5557dd7cddfSDavid du Colombier
5567dd7cddfSDavid du Colombier return p;
5577dd7cddfSDavid du Colombier }
5587dd7cddfSDavid du Colombier
5597dd7cddfSDavid du Colombier static void
clipy(Memimage * img,int * y)5607dd7cddfSDavid du Colombier clipy(Memimage *img, int *y)
5617dd7cddfSDavid du Colombier {
5627dd7cddfSDavid du Colombier int dy;
5637dd7cddfSDavid du Colombier
5647dd7cddfSDavid du Colombier dy = Dy(img->r);
5657dd7cddfSDavid du Colombier if(*y == dy)
5667dd7cddfSDavid du Colombier *y = 0;
5677dd7cddfSDavid du Colombier else if(*y == -1)
5687dd7cddfSDavid du Colombier *y = dy-1;
5697dd7cddfSDavid du Colombier assert(0 <= *y && *y < dy);
5707dd7cddfSDavid du Colombier }
5717dd7cddfSDavid du Colombier
5727dd7cddfSDavid du Colombier static void
dumpbuf(char * s,Buffer b,int n)5737dd7cddfSDavid du Colombier dumpbuf(char *s, Buffer b, int n)
5747dd7cddfSDavid du Colombier {
5757dd7cddfSDavid du Colombier int i;
5767dd7cddfSDavid du Colombier uchar *p;
5777dd7cddfSDavid du Colombier
5787dd7cddfSDavid du Colombier print("%s", s);
5797dd7cddfSDavid du Colombier for(i=0; i<n; i++){
5807dd7cddfSDavid du Colombier print(" ");
5818ccd4a63SDavid du Colombier if((p=b.grey)){
5827dd7cddfSDavid du Colombier print(" k%.2uX", *p);
5837dd7cddfSDavid du Colombier b.grey += b.delta;
5847dd7cddfSDavid du Colombier }else{
5858ccd4a63SDavid du Colombier if((p=b.red)){
5867dd7cddfSDavid du Colombier print(" r%.2uX", *p);
5877dd7cddfSDavid du Colombier b.red += b.delta;
5887dd7cddfSDavid du Colombier }
5898ccd4a63SDavid du Colombier if((p=b.grn)){
5907dd7cddfSDavid du Colombier print(" g%.2uX", *p);
5917dd7cddfSDavid du Colombier b.grn += b.delta;
5927dd7cddfSDavid du Colombier }
5938ccd4a63SDavid du Colombier if((p=b.blu)){
5947dd7cddfSDavid du Colombier print(" b%.2uX", *p);
5957dd7cddfSDavid du Colombier b.blu += b.delta;
5967dd7cddfSDavid du Colombier }
5977dd7cddfSDavid du Colombier }
5988ccd4a63SDavid du Colombier if((p=b.alpha) != &ones){
5997dd7cddfSDavid du Colombier print(" α%.2uX", *p);
6007dd7cddfSDavid du Colombier b.alpha += b.delta;
6017dd7cddfSDavid du Colombier }
6027dd7cddfSDavid du Colombier }
6037dd7cddfSDavid du Colombier print("\n");
6047dd7cddfSDavid du Colombier }
6057dd7cddfSDavid du Colombier
6067dd7cddfSDavid du Colombier /*
6077dd7cddfSDavid du Colombier * For each scan line, we expand the pixels from source, mask, and destination
6087dd7cddfSDavid du Colombier * into byte-aligned red, green, blue, alpha, and grey channels. If buffering is not
6097dd7cddfSDavid du Colombier * needed and the channels were already byte-aligned (grey8, rgb24, rgba32, rgb32),
6107dd7cddfSDavid du Colombier * the readers need not copy the data: they can simply return pointers to the data.
6117dd7cddfSDavid du Colombier * If the destination image is grey and the source is not, it is converted using the NTSC
6127dd7cddfSDavid du Colombier * formula.
6137dd7cddfSDavid du Colombier *
6147dd7cddfSDavid du Colombier * Once we have all the channels, we call either rgbcalc or greycalc, depending on
6157dd7cddfSDavid du Colombier * whether the destination image is color. This is allowed to overwrite the dst buffer (perhaps
6167dd7cddfSDavid du Colombier * the actual data, perhaps a copy) with its result. It should only overwrite the dst buffer
6177dd7cddfSDavid du Colombier * with the same format (i.e. red bytes with red bytes, etc.) A new buffer is returned from
6187dd7cddfSDavid du Colombier * the calculator, and that buffer is passed to a function to write it to the destination.
6197dd7cddfSDavid du Colombier * If the buffer is already pointing at the destination, the writing function is a no-op.
6207dd7cddfSDavid du Colombier */
6217dd7cddfSDavid du Colombier #define DBG if(0)
6227dd7cddfSDavid du Colombier static int
alphadraw(Memdrawparam * par)6237dd7cddfSDavid du Colombier alphadraw(Memdrawparam *par)
6247dd7cddfSDavid du Colombier {
6258ccd4a63SDavid du Colombier int isgrey, starty, endy, op;
6267dd7cddfSDavid du Colombier int needbuf, dsty, srcy, masky;
6277dd7cddfSDavid du Colombier int y, dir, dx, dy;
6287dd7cddfSDavid du Colombier Buffer bsrc, bdst, bmask;
6297dd7cddfSDavid du Colombier Readfn *rdsrc, *rdmask, *rddst;
6307dd7cddfSDavid du Colombier Calcfn *calc;
6317dd7cddfSDavid du Colombier Writefn *wrdst;
6327dd7cddfSDavid du Colombier Memimage *src, *mask, *dst;
6337dd7cddfSDavid du Colombier Rectangle r, sr, mr;
6347dd7cddfSDavid du Colombier
6357dd7cddfSDavid du Colombier r = par->r;
6367dd7cddfSDavid du Colombier dx = Dx(r);
6377dd7cddfSDavid du Colombier dy = Dy(r);
6387dd7cddfSDavid du Colombier
6397dd7cddfSDavid du Colombier ndrawbuf = 0;
6407dd7cddfSDavid du Colombier
6417dd7cddfSDavid du Colombier src = par->src;
6427dd7cddfSDavid du Colombier mask = par->mask;
6437dd7cddfSDavid du Colombier dst = par->dst;
6447dd7cddfSDavid du Colombier sr = par->sr;
6457dd7cddfSDavid du Colombier mr = par->mr;
6468ccd4a63SDavid du Colombier op = par->op;
6477dd7cddfSDavid du Colombier
6487dd7cddfSDavid du Colombier isgrey = dst->flags&Fgrey;
6497dd7cddfSDavid du Colombier
6507dd7cddfSDavid du Colombier /*
6517dd7cddfSDavid du Colombier * Buffering when src and dst are the same bitmap is sufficient but not
6527dd7cddfSDavid du Colombier * necessary. There are stronger conditions we could use. We could
6537dd7cddfSDavid du Colombier * check to see if the rectangles intersect, and if simply moving in the
6547dd7cddfSDavid du Colombier * correct y direction can avoid the need to buffer.
6557dd7cddfSDavid du Colombier */
6567dd7cddfSDavid du Colombier needbuf = (src->data == dst->data);
6577dd7cddfSDavid du Colombier
6587dd7cddfSDavid du Colombier spar = getparam(src, sr, isgrey, needbuf);
6597dd7cddfSDavid du Colombier dpar = getparam(dst, r, isgrey, needbuf);
6608ccd4a63SDavid du Colombier mpar = getparam(mask, mr, 0, needbuf);
6617dd7cddfSDavid du Colombier
6627dd7cddfSDavid du Colombier dir = (needbuf && byteaddr(dst, r.min) > byteaddr(src, sr.min)) ? -1 : 1;
6637dd7cddfSDavid du Colombier spar.dir = mpar.dir = dpar.dir = dir;
6647dd7cddfSDavid du Colombier
6657dd7cddfSDavid du Colombier /*
6667dd7cddfSDavid du Colombier * If the mask is purely boolean, we can convert from src to dst format
6677dd7cddfSDavid du Colombier * when we read src, and then just copy it to dst where the mask tells us to.
6687dd7cddfSDavid du Colombier * This requires a boolean (1-bit grey) mask and lack of a source alpha channel.
6697dd7cddfSDavid du Colombier *
6707dd7cddfSDavid du Colombier * The computation is accomplished by assigning the function pointers as follows:
6717dd7cddfSDavid du Colombier * rdsrc - read and convert source into dst format in a buffer
6727dd7cddfSDavid du Colombier * rdmask - convert mask to bytes, set pointer to it
6737dd7cddfSDavid du Colombier * rddst - fill with pointer to real dst data, but do no reads
6747dd7cddfSDavid du Colombier * calc - copy src onto dst when mask says to.
6757dd7cddfSDavid du Colombier * wrdst - do nothing
6767dd7cddfSDavid du Colombier * This is slightly sleazy, since things aren't doing exactly what their names say,
6777dd7cddfSDavid du Colombier * but it avoids a fair amount of code duplication to make this a case here
6787dd7cddfSDavid du Colombier * rather than have a separate booldraw.
6797dd7cddfSDavid du Colombier */
6808ccd4a63SDavid du Colombier //if(drawdebug) iprint("flag %lud mchan %lux=?%x dd %d\n", src->flags&Falpha, mask->chan, GREY1, dst->depth);
6818ccd4a63SDavid du Colombier if(!(src->flags&Falpha) && mask->chan == GREY1 && dst->depth >= 8 && op == SoverD){
6828ccd4a63SDavid du Colombier //if(drawdebug) iprint("boolcopy...");
6837dd7cddfSDavid du Colombier rdsrc = convfn(dst, &dpar, src, &spar);
6847dd7cddfSDavid du Colombier rddst = readptr;
6857dd7cddfSDavid du Colombier rdmask = readfn(mask);
6867dd7cddfSDavid du Colombier calc = boolcopyfn(dst, mask);
6877dd7cddfSDavid du Colombier wrdst = nullwrite;
6887dd7cddfSDavid du Colombier }else{
6897dd7cddfSDavid du Colombier /* usual alphadraw parameter fetching */
6907dd7cddfSDavid du Colombier rdsrc = readfn(src);
6917dd7cddfSDavid du Colombier rddst = readfn(dst);
6927dd7cddfSDavid du Colombier wrdst = writefn(dst);
6938ccd4a63SDavid du Colombier calc = alphacalc[op];
6947dd7cddfSDavid du Colombier
6957dd7cddfSDavid du Colombier /*
6967dd7cddfSDavid du Colombier * If there is no alpha channel, we'll ask for a grey channel
6977dd7cddfSDavid du Colombier * and pretend it is the alpha.
6987dd7cddfSDavid du Colombier */
6997dd7cddfSDavid du Colombier if(mask->flags&Falpha){
7007dd7cddfSDavid du Colombier rdmask = readalphafn(mask);
7017dd7cddfSDavid du Colombier mpar.alphaonly = 1;
7027dd7cddfSDavid du Colombier }else{
7037dd7cddfSDavid du Colombier mpar.greymaskcall = readfn(mask);
7047dd7cddfSDavid du Colombier mpar.convgrey = 1;
7057dd7cddfSDavid du Colombier rdmask = greymaskread;
7067dd7cddfSDavid du Colombier
7077dd7cddfSDavid du Colombier /*
7087dd7cddfSDavid du Colombier * Should really be above, but then boolcopyfns would have
7097dd7cddfSDavid du Colombier * to deal with bit alignment, and I haven't written that.
7107dd7cddfSDavid du Colombier *
7117dd7cddfSDavid du Colombier * This is a common case for things like ellipse drawing.
7127dd7cddfSDavid du Colombier * When there's no alpha involved and the mask is boolean,
7137dd7cddfSDavid du Colombier * we can avoid all the division and multiplication.
7147dd7cddfSDavid du Colombier */
7157dd7cddfSDavid du Colombier if(mask->chan == GREY1 && !(src->flags&Falpha))
7168ccd4a63SDavid du Colombier calc = boolcalc[op];
7178ccd4a63SDavid du Colombier else if(op == SoverD && !(src->flags&Falpha))
7188ccd4a63SDavid du Colombier calc = alphacalcS;
7197dd7cddfSDavid du Colombier }
7207dd7cddfSDavid du Colombier }
7217dd7cddfSDavid du Colombier
7227dd7cddfSDavid du Colombier /*
7237dd7cddfSDavid du Colombier * If the image has a small enough repl rectangle,
7247dd7cddfSDavid du Colombier * we can just read each line once and cache them.
7257dd7cddfSDavid du Colombier */
7267dd7cddfSDavid du Colombier if(spar.replcache){
7277dd7cddfSDavid du Colombier spar.replcall = rdsrc;
7287dd7cddfSDavid du Colombier rdsrc = replread;
7297dd7cddfSDavid du Colombier }
7307dd7cddfSDavid du Colombier if(mpar.replcache){
7317dd7cddfSDavid du Colombier mpar.replcall = rdmask;
7327dd7cddfSDavid du Colombier rdmask = replread;
7337dd7cddfSDavid du Colombier }
7347dd7cddfSDavid du Colombier
7357dd7cddfSDavid du Colombier if(allocdrawbuf() < 0)
7367dd7cddfSDavid du Colombier return 0;
7377dd7cddfSDavid du Colombier
7387dd7cddfSDavid du Colombier /*
7397dd7cddfSDavid du Colombier * Before we were saving only offsets from drawbuf in the parameter
7407dd7cddfSDavid du Colombier * structures; now that drawbuf has been grown to accomodate us,
7417dd7cddfSDavid du Colombier * we can fill in the pointers.
7427dd7cddfSDavid du Colombier */
7437dd7cddfSDavid du Colombier spar.bufbase = drawbuf+spar.bufoff;
7447dd7cddfSDavid du Colombier mpar.bufbase = drawbuf+mpar.bufoff;
7457dd7cddfSDavid du Colombier dpar.bufbase = drawbuf+dpar.bufoff;
7467dd7cddfSDavid du Colombier spar.convbuf = drawbuf+spar.convbufoff;
7477dd7cddfSDavid du Colombier
7487dd7cddfSDavid du Colombier if(dir == 1){
7497dd7cddfSDavid du Colombier starty = 0;
7507dd7cddfSDavid du Colombier endy = dy;
7517dd7cddfSDavid du Colombier }else{
7527dd7cddfSDavid du Colombier starty = dy-1;
7537dd7cddfSDavid du Colombier endy = -1;
7547dd7cddfSDavid du Colombier }
7557dd7cddfSDavid du Colombier
7567dd7cddfSDavid du Colombier /*
7577dd7cddfSDavid du Colombier * srcy, masky, and dsty are offsets from the top of their
7587dd7cddfSDavid du Colombier * respective Rectangles. they need to be contained within
7597dd7cddfSDavid du Colombier * the rectangles, so clipy can keep them there without division.
7607dd7cddfSDavid du Colombier */
7617dd7cddfSDavid du Colombier srcy = (starty + sr.min.y - src->r.min.y)%Dy(src->r);
7627dd7cddfSDavid du Colombier masky = (starty + mr.min.y - mask->r.min.y)%Dy(mask->r);
7637dd7cddfSDavid du Colombier dsty = starty + r.min.y - dst->r.min.y;
7647dd7cddfSDavid du Colombier
7657dd7cddfSDavid du Colombier assert(0 <= srcy && srcy < Dy(src->r));
7667dd7cddfSDavid du Colombier assert(0 <= masky && masky < Dy(mask->r));
7677dd7cddfSDavid du Colombier assert(0 <= dsty && dsty < Dy(dst->r));
7687dd7cddfSDavid du Colombier
7697dd7cddfSDavid du Colombier for(y=starty; y!=endy; y+=dir, srcy+=dir, masky+=dir, dsty+=dir){
7707dd7cddfSDavid du Colombier clipy(src, &srcy);
7717dd7cddfSDavid du Colombier clipy(dst, &dsty);
7727dd7cddfSDavid du Colombier clipy(mask, &masky);
7737dd7cddfSDavid du Colombier
7747dd7cddfSDavid du Colombier bsrc = rdsrc(&spar, spar.bufbase, srcy);
7757dd7cddfSDavid du Colombier DBG print("[");
7767dd7cddfSDavid du Colombier bmask = rdmask(&mpar, mpar.bufbase, masky);
7777dd7cddfSDavid du Colombier DBG print("]\n");
7787dd7cddfSDavid du Colombier bdst = rddst(&dpar, dpar.bufbase, dsty);
7797dd7cddfSDavid du Colombier DBG dumpbuf("src", bsrc, dx);
7807dd7cddfSDavid du Colombier DBG dumpbuf("mask", bmask, dx);
7817dd7cddfSDavid du Colombier DBG dumpbuf("dst", bdst, dx);
7828ccd4a63SDavid du Colombier bdst = calc(bdst, bsrc, bmask, dx, isgrey, op);
7837dd7cddfSDavid du Colombier wrdst(&dpar, dpar.bytermin+dsty*dpar.bwidth, bdst);
7847dd7cddfSDavid du Colombier }
7857dd7cddfSDavid du Colombier
7867dd7cddfSDavid du Colombier return 1;
7877dd7cddfSDavid du Colombier }
7887dd7cddfSDavid du Colombier #undef DBG
7897dd7cddfSDavid du Colombier
7907dd7cddfSDavid du Colombier static Buffer
alphacalc0(Buffer bdst,Buffer b1,Buffer b2,int dx,int grey,int op)7918ccd4a63SDavid du Colombier alphacalc0(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op)
7928ccd4a63SDavid du Colombier {
7938ccd4a63SDavid du Colombier USED(grey);
7948ccd4a63SDavid du Colombier USED(op);
7958ccd4a63SDavid du Colombier memset(bdst.rgba, 0, dx*bdst.delta);
7968ccd4a63SDavid du Colombier return bdst;
7978ccd4a63SDavid du Colombier }
7988ccd4a63SDavid du Colombier
799*58da3067SDavid du Colombier /*
800*58da3067SDavid du Colombier * Do the channels in the buffers match enough
801*58da3067SDavid du Colombier * that we can do word-at-a-time operations
802*58da3067SDavid du Colombier * on the pixels?
803*58da3067SDavid du Colombier */
804*58da3067SDavid du Colombier static int
chanmatch(Buffer * bdst,Buffer * bsrc)805*58da3067SDavid du Colombier chanmatch(Buffer *bdst, Buffer *bsrc)
806*58da3067SDavid du Colombier {
807*58da3067SDavid du Colombier uchar *drgb, *srgb;
808*58da3067SDavid du Colombier
809*58da3067SDavid du Colombier /*
810*58da3067SDavid du Colombier * first, r, g, b must be in the same place
811*58da3067SDavid du Colombier * in the rgba word.
812*58da3067SDavid du Colombier */
813*58da3067SDavid du Colombier drgb = (uchar*)bdst->rgba;
814*58da3067SDavid du Colombier srgb = (uchar*)bsrc->rgba;
815*58da3067SDavid du Colombier if(bdst->red - drgb != bsrc->red - srgb
816*58da3067SDavid du Colombier || bdst->blu - drgb != bsrc->blu - srgb
817*58da3067SDavid du Colombier || bdst->grn - drgb != bsrc->grn - srgb)
818*58da3067SDavid du Colombier return 0;
819*58da3067SDavid du Colombier
820*58da3067SDavid du Colombier /*
821*58da3067SDavid du Colombier * that implies alpha is in the same place,
822*58da3067SDavid du Colombier * if it is there at all (it might be == &ones).
823*58da3067SDavid du Colombier * if the destination is &ones, we can scribble
824*58da3067SDavid du Colombier * over the rgba slot just fine.
825*58da3067SDavid du Colombier */
826*58da3067SDavid du Colombier if(bdst->alpha == &ones)
827*58da3067SDavid du Colombier return 1;
828*58da3067SDavid du Colombier
829*58da3067SDavid du Colombier /*
830*58da3067SDavid du Colombier * if the destination is not ones but the src is,
831*58da3067SDavid du Colombier * then the simultaneous calculation will use
832*58da3067SDavid du Colombier * bogus bytes from the src's rgba. no good.
833*58da3067SDavid du Colombier */
834*58da3067SDavid du Colombier if(bsrc->alpha == &ones)
835*58da3067SDavid du Colombier return 0;
836*58da3067SDavid du Colombier
837*58da3067SDavid du Colombier /*
838*58da3067SDavid du Colombier * otherwise, alphas are in the same place.
839*58da3067SDavid du Colombier */
840*58da3067SDavid du Colombier return 1;
841*58da3067SDavid du Colombier }
842*58da3067SDavid du Colombier
8438ccd4a63SDavid du Colombier static Buffer
alphacalc14(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)8448ccd4a63SDavid du Colombier alphacalc14(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
8457dd7cddfSDavid du Colombier {
8467dd7cddfSDavid du Colombier Buffer obdst;
8478ccd4a63SDavid du Colombier int fd, sadelta;
8488ccd4a63SDavid du Colombier int i, sa, ma, q;
849*58da3067SDavid du Colombier ulong t, t1;
8507dd7cddfSDavid du Colombier
8517dd7cddfSDavid du Colombier obdst = bdst;
8528ccd4a63SDavid du Colombier sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
853*58da3067SDavid du Colombier q = bsrc.delta == 4 && bdst.delta == 4 && chanmatch(&bdst, &bsrc);
8547dd7cddfSDavid du Colombier
8557dd7cddfSDavid du Colombier for(i=0; i<dx; i++){
8568ccd4a63SDavid du Colombier sa = *bsrc.alpha;
8577dd7cddfSDavid du Colombier ma = *bmask.alpha;
858*58da3067SDavid du Colombier fd = CALC11(sa, ma, t);
8598ccd4a63SDavid du Colombier if(op == DoutS)
8608ccd4a63SDavid du Colombier fd = 255-fd;
8617dd7cddfSDavid du Colombier
8627dd7cddfSDavid du Colombier if(grey){
863*58da3067SDavid du Colombier *bdst.grey = CALC11(fd, *bdst.grey, t);
8647dd7cddfSDavid du Colombier bsrc.grey += bsrc.delta;
8657dd7cddfSDavid du Colombier bdst.grey += bdst.delta;
8667dd7cddfSDavid du Colombier }else{
8678ccd4a63SDavid du Colombier if(q){
868*58da3067SDavid du Colombier *bdst.rgba = CALC41(fd, *bdst.rgba, t, t1);
8698ccd4a63SDavid du Colombier bsrc.rgba++;
8708ccd4a63SDavid du Colombier bdst.rgba++;
8718ccd4a63SDavid du Colombier bsrc.alpha += sadelta;
8728ccd4a63SDavid du Colombier bmask.alpha += bmask.delta;
8738ccd4a63SDavid du Colombier continue;
8748ccd4a63SDavid du Colombier }
875*58da3067SDavid du Colombier *bdst.red = CALC11(fd, *bdst.red, t);
876*58da3067SDavid du Colombier *bdst.grn = CALC11(fd, *bdst.grn, t);
877*58da3067SDavid du Colombier *bdst.blu = CALC11(fd, *bdst.blu, t);
8787dd7cddfSDavid du Colombier bsrc.red += bsrc.delta;
8797dd7cddfSDavid du Colombier bsrc.blu += bsrc.delta;
8807dd7cddfSDavid du Colombier bsrc.grn += bsrc.delta;
8817dd7cddfSDavid du Colombier bdst.red += bdst.delta;
8827dd7cddfSDavid du Colombier bdst.blu += bdst.delta;
8837dd7cddfSDavid du Colombier bdst.grn += bdst.delta;
8847dd7cddfSDavid du Colombier }
8858ccd4a63SDavid du Colombier if(bdst.alpha != &ones){
886*58da3067SDavid du Colombier *bdst.alpha = CALC11(fd, *bdst.alpha, t);
8878ccd4a63SDavid du Colombier bdst.alpha += bdst.delta;
8888ccd4a63SDavid du Colombier }
8897dd7cddfSDavid du Colombier bmask.alpha += bmask.delta;
8908ccd4a63SDavid du Colombier bsrc.alpha += sadelta;
8918ccd4a63SDavid du Colombier }
8928ccd4a63SDavid du Colombier return obdst;
8938ccd4a63SDavid du Colombier }
8947dd7cddfSDavid du Colombier
8958ccd4a63SDavid du Colombier static Buffer
alphacalc2810(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)8968ccd4a63SDavid du Colombier alphacalc2810(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
8978ccd4a63SDavid du Colombier {
8988ccd4a63SDavid du Colombier Buffer obdst;
8998ccd4a63SDavid du Colombier int fs, sadelta;
9008ccd4a63SDavid du Colombier int i, ma, da, q;
901*58da3067SDavid du Colombier ulong t, t1;
9028ccd4a63SDavid du Colombier
9038ccd4a63SDavid du Colombier obdst = bdst;
9048ccd4a63SDavid du Colombier sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
905*58da3067SDavid du Colombier q = bsrc.delta == 4 && bdst.delta == 4 && chanmatch(&bdst, &bsrc);
9068ccd4a63SDavid du Colombier
9078ccd4a63SDavid du Colombier for(i=0; i<dx; i++){
9088ccd4a63SDavid du Colombier ma = *bmask.alpha;
9098ccd4a63SDavid du Colombier da = *bdst.alpha;
9108ccd4a63SDavid du Colombier if(op == SoutD)
9118ccd4a63SDavid du Colombier da = 255-da;
9128ccd4a63SDavid du Colombier fs = ma;
9138ccd4a63SDavid du Colombier if(op != S)
914*58da3067SDavid du Colombier fs = CALC11(fs, da, t);
9158ccd4a63SDavid du Colombier
9168ccd4a63SDavid du Colombier if(grey){
917*58da3067SDavid du Colombier *bdst.grey = CALC11(fs, *bsrc.grey, t);
9188ccd4a63SDavid du Colombier bsrc.grey += bsrc.delta;
9198ccd4a63SDavid du Colombier bdst.grey += bdst.delta;
9208ccd4a63SDavid du Colombier }else{
9218ccd4a63SDavid du Colombier if(q){
922*58da3067SDavid du Colombier *bdst.rgba = CALC41(fs, *bsrc.rgba, t, t1);
9238ccd4a63SDavid du Colombier bsrc.rgba++;
9248ccd4a63SDavid du Colombier bdst.rgba++;
9258ccd4a63SDavid du Colombier bmask.alpha += bmask.delta;
9268ccd4a63SDavid du Colombier bdst.alpha += bdst.delta;
9278ccd4a63SDavid du Colombier continue;
9288ccd4a63SDavid du Colombier }
929*58da3067SDavid du Colombier *bdst.red = CALC11(fs, *bsrc.red, t);
930*58da3067SDavid du Colombier *bdst.grn = CALC11(fs, *bsrc.grn, t);
931*58da3067SDavid du Colombier *bdst.blu = CALC11(fs, *bsrc.blu, t);
9328ccd4a63SDavid du Colombier bsrc.red += bsrc.delta;
9338ccd4a63SDavid du Colombier bsrc.blu += bsrc.delta;
9348ccd4a63SDavid du Colombier bsrc.grn += bsrc.delta;
9358ccd4a63SDavid du Colombier bdst.red += bdst.delta;
9368ccd4a63SDavid du Colombier bdst.blu += bdst.delta;
9378ccd4a63SDavid du Colombier bdst.grn += bdst.delta;
9388ccd4a63SDavid du Colombier }
9398ccd4a63SDavid du Colombier if(bdst.alpha != &ones){
940*58da3067SDavid du Colombier *bdst.alpha = CALC11(fs, *bsrc.alpha, t);
9418ccd4a63SDavid du Colombier bdst.alpha += bdst.delta;
9428ccd4a63SDavid du Colombier }
9438ccd4a63SDavid du Colombier bmask.alpha += bmask.delta;
9448ccd4a63SDavid du Colombier bsrc.alpha += sadelta;
9458ccd4a63SDavid du Colombier }
9468ccd4a63SDavid du Colombier return obdst;
9478ccd4a63SDavid du Colombier }
9488ccd4a63SDavid du Colombier
9498ccd4a63SDavid du Colombier static Buffer
alphacalc3679(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)9508ccd4a63SDavid du Colombier alphacalc3679(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
9518ccd4a63SDavid du Colombier {
9528ccd4a63SDavid du Colombier Buffer obdst;
9538ccd4a63SDavid du Colombier int fs, fd, sadelta;
9548ccd4a63SDavid du Colombier int i, sa, ma, da, q;
955*58da3067SDavid du Colombier ulong t, t1;
9568ccd4a63SDavid du Colombier
9578ccd4a63SDavid du Colombier obdst = bdst;
9588ccd4a63SDavid du Colombier sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
959*58da3067SDavid du Colombier q = bsrc.delta == 4 && bdst.delta == 4 && chanmatch(&bdst, &bsrc);
9608ccd4a63SDavid du Colombier
9618ccd4a63SDavid du Colombier for(i=0; i<dx; i++){
9628ccd4a63SDavid du Colombier sa = *bsrc.alpha;
9638ccd4a63SDavid du Colombier ma = *bmask.alpha;
9648ccd4a63SDavid du Colombier da = *bdst.alpha;
9658ccd4a63SDavid du Colombier if(op == SatopD)
966*58da3067SDavid du Colombier fs = CALC11(ma, da, t);
9678ccd4a63SDavid du Colombier else
968*58da3067SDavid du Colombier fs = CALC11(ma, 255-da, t);
9698ccd4a63SDavid du Colombier if(op == DoverS)
9708ccd4a63SDavid du Colombier fd = 255;
9718ccd4a63SDavid du Colombier else{
972*58da3067SDavid du Colombier fd = CALC11(sa, ma, t);
9738ccd4a63SDavid du Colombier if(op != DatopS)
9748ccd4a63SDavid du Colombier fd = 255-fd;
9758ccd4a63SDavid du Colombier }
9768ccd4a63SDavid du Colombier
9778ccd4a63SDavid du Colombier if(grey){
978*58da3067SDavid du Colombier *bdst.grey = CALC12(fs, *bsrc.grey, fd, *bdst.grey, t);
9798ccd4a63SDavid du Colombier bsrc.grey += bsrc.delta;
9808ccd4a63SDavid du Colombier bdst.grey += bdst.delta;
9818ccd4a63SDavid du Colombier }else{
9828ccd4a63SDavid du Colombier if(q){
983*58da3067SDavid du Colombier *bdst.rgba = CALC42(fs, *bsrc.rgba, fd, *bdst.rgba, t, t1);
9848ccd4a63SDavid du Colombier bsrc.rgba++;
9858ccd4a63SDavid du Colombier bdst.rgba++;
9868ccd4a63SDavid du Colombier bsrc.alpha += sadelta;
9878ccd4a63SDavid du Colombier bmask.alpha += bmask.delta;
9888ccd4a63SDavid du Colombier bdst.alpha += bdst.delta;
9898ccd4a63SDavid du Colombier continue;
9908ccd4a63SDavid du Colombier }
991*58da3067SDavid du Colombier *bdst.red = CALC12(fs, *bsrc.red, fd, *bdst.red, t);
992*58da3067SDavid du Colombier *bdst.grn = CALC12(fs, *bsrc.grn, fd, *bdst.grn, t);
993*58da3067SDavid du Colombier *bdst.blu = CALC12(fs, *bsrc.blu, fd, *bdst.blu, t);
9948ccd4a63SDavid du Colombier bsrc.red += bsrc.delta;
9958ccd4a63SDavid du Colombier bsrc.blu += bsrc.delta;
9968ccd4a63SDavid du Colombier bsrc.grn += bsrc.delta;
9978ccd4a63SDavid du Colombier bdst.red += bdst.delta;
9988ccd4a63SDavid du Colombier bdst.blu += bdst.delta;
9998ccd4a63SDavid du Colombier bdst.grn += bdst.delta;
10008ccd4a63SDavid du Colombier }
10018ccd4a63SDavid du Colombier if(bdst.alpha != &ones){
1002*58da3067SDavid du Colombier *bdst.alpha = CALC12(fs, sa, fd, da, t);
10038ccd4a63SDavid du Colombier bdst.alpha += bdst.delta;
10048ccd4a63SDavid du Colombier }
10058ccd4a63SDavid du Colombier bmask.alpha += bmask.delta;
10068ccd4a63SDavid du Colombier bsrc.alpha += sadelta;
10078ccd4a63SDavid du Colombier }
10088ccd4a63SDavid du Colombier return obdst;
10098ccd4a63SDavid du Colombier }
10108ccd4a63SDavid du Colombier
10118ccd4a63SDavid du Colombier static Buffer
alphacalc5(Buffer bdst,Buffer b1,Buffer b2,int dx,int grey,int op)10128ccd4a63SDavid du Colombier alphacalc5(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op)
10138ccd4a63SDavid du Colombier {
10148ccd4a63SDavid du Colombier USED(dx);
10158ccd4a63SDavid du Colombier USED(grey);
10168ccd4a63SDavid du Colombier USED(op);
10178ccd4a63SDavid du Colombier return bdst;
10188ccd4a63SDavid du Colombier }
10198ccd4a63SDavid du Colombier
10208ccd4a63SDavid du Colombier static Buffer
alphacalc11(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)10218ccd4a63SDavid du Colombier alphacalc11(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
10228ccd4a63SDavid du Colombier {
10238ccd4a63SDavid du Colombier Buffer obdst;
10248ccd4a63SDavid du Colombier int fd, sadelta;
10258ccd4a63SDavid du Colombier int i, sa, ma, q;
1026*58da3067SDavid du Colombier ulong t, t1;
10278ccd4a63SDavid du Colombier
10288ccd4a63SDavid du Colombier USED(op);
10298ccd4a63SDavid du Colombier obdst = bdst;
10308ccd4a63SDavid du Colombier sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta;
1031*58da3067SDavid du Colombier q = bsrc.delta == 4 && bdst.delta == 4 && chanmatch(&bdst, &bsrc);
10328ccd4a63SDavid du Colombier
10338ccd4a63SDavid du Colombier for(i=0; i<dx; i++){
10348ccd4a63SDavid du Colombier sa = *bsrc.alpha;
10358ccd4a63SDavid du Colombier ma = *bmask.alpha;
1036*58da3067SDavid du Colombier fd = 255-CALC11(sa, ma, t);
10378ccd4a63SDavid du Colombier
10388ccd4a63SDavid du Colombier if(grey){
1039*58da3067SDavid du Colombier *bdst.grey = CALC12(ma, *bsrc.grey, fd, *bdst.grey, t);
10408ccd4a63SDavid du Colombier bsrc.grey += bsrc.delta;
10418ccd4a63SDavid du Colombier bdst.grey += bdst.delta;
10428ccd4a63SDavid du Colombier }else{
10438ccd4a63SDavid du Colombier if(q){
1044*58da3067SDavid du Colombier *bdst.rgba = CALC42(ma, *bsrc.rgba, fd, *bdst.rgba, t, t1);
10458ccd4a63SDavid du Colombier bsrc.rgba++;
10468ccd4a63SDavid du Colombier bdst.rgba++;
10478ccd4a63SDavid du Colombier bsrc.alpha += sadelta;
10488ccd4a63SDavid du Colombier bmask.alpha += bmask.delta;
10498ccd4a63SDavid du Colombier continue;
10508ccd4a63SDavid du Colombier }
1051*58da3067SDavid du Colombier *bdst.red = CALC12(ma, *bsrc.red, fd, *bdst.red, t);
1052*58da3067SDavid du Colombier *bdst.grn = CALC12(ma, *bsrc.grn, fd, *bdst.grn, t);
1053*58da3067SDavid du Colombier *bdst.blu = CALC12(ma, *bsrc.blu, fd, *bdst.blu, t);
10548ccd4a63SDavid du Colombier bsrc.red += bsrc.delta;
10558ccd4a63SDavid du Colombier bsrc.blu += bsrc.delta;
10568ccd4a63SDavid du Colombier bsrc.grn += bsrc.delta;
10578ccd4a63SDavid du Colombier bdst.red += bdst.delta;
10588ccd4a63SDavid du Colombier bdst.blu += bdst.delta;
10598ccd4a63SDavid du Colombier bdst.grn += bdst.delta;
10608ccd4a63SDavid du Colombier }
10618ccd4a63SDavid du Colombier if(bdst.alpha != &ones){
1062*58da3067SDavid du Colombier *bdst.alpha = CALC12(ma, sa, fd, *bdst.alpha, t);
10638ccd4a63SDavid du Colombier bdst.alpha += bdst.delta;
10648ccd4a63SDavid du Colombier }
10658ccd4a63SDavid du Colombier bmask.alpha += bmask.delta;
10668ccd4a63SDavid du Colombier bsrc.alpha += sadelta;
10678ccd4a63SDavid du Colombier }
10688ccd4a63SDavid du Colombier return obdst;
10698ccd4a63SDavid du Colombier }
10708ccd4a63SDavid du Colombier
10718ccd4a63SDavid du Colombier /*
10728ccd4a63SDavid du Colombier not used yet
10738ccd4a63SDavid du Colombier source and mask alpha 1
10748ccd4a63SDavid du Colombier static Buffer
10758ccd4a63SDavid du Colombier alphacalcS0(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
10768ccd4a63SDavid du Colombier {
10778ccd4a63SDavid du Colombier Buffer obdst;
10788ccd4a63SDavid du Colombier int i;
10798ccd4a63SDavid du Colombier
10808ccd4a63SDavid du Colombier USED(op);
10818ccd4a63SDavid du Colombier obdst = bdst;
10828ccd4a63SDavid du Colombier if(bsrc.delta == bdst.delta){
10838ccd4a63SDavid du Colombier memmove(bdst.rgba, bsrc.rgba, dx*bdst.delta);
10848ccd4a63SDavid du Colombier return obdst;
10858ccd4a63SDavid du Colombier }
10868ccd4a63SDavid du Colombier for(i=0; i<dx; i++){
10878ccd4a63SDavid du Colombier if(grey){
10888ccd4a63SDavid du Colombier *bdst.grey = *bsrc.grey;
10898ccd4a63SDavid du Colombier bsrc.grey += bsrc.delta;
10908ccd4a63SDavid du Colombier bdst.grey += bdst.delta;
10918ccd4a63SDavid du Colombier }else{
10928ccd4a63SDavid du Colombier *bdst.red = *bsrc.red;
10938ccd4a63SDavid du Colombier *bdst.grn = *bsrc.grn;
10948ccd4a63SDavid du Colombier *bdst.blu = *bsrc.blu;
10958ccd4a63SDavid du Colombier bsrc.red += bsrc.delta;
10968ccd4a63SDavid du Colombier bsrc.blu += bsrc.delta;
10978ccd4a63SDavid du Colombier bsrc.grn += bsrc.delta;
10988ccd4a63SDavid du Colombier bdst.red += bdst.delta;
10998ccd4a63SDavid du Colombier bdst.blu += bdst.delta;
11008ccd4a63SDavid du Colombier bdst.grn += bdst.delta;
11018ccd4a63SDavid du Colombier }
11028ccd4a63SDavid du Colombier if(bdst.alpha != &ones){
11038ccd4a63SDavid du Colombier *bdst.alpha = 255;
11047dd7cddfSDavid du Colombier bdst.alpha += bdst.delta;
11057dd7cddfSDavid du Colombier }
11067dd7cddfSDavid du Colombier }
11077dd7cddfSDavid du Colombier return obdst;
11087dd7cddfSDavid du Colombier }
11098ccd4a63SDavid du Colombier */
11107dd7cddfSDavid du Colombier
11118ccd4a63SDavid du Colombier /* source alpha 1 */
11127dd7cddfSDavid du Colombier static Buffer
alphacalcS(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)11138ccd4a63SDavid du Colombier alphacalcS(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
11147dd7cddfSDavid du Colombier {
11157dd7cddfSDavid du Colombier Buffer obdst;
11168ccd4a63SDavid du Colombier int fd;
11177dd7cddfSDavid du Colombier int i, ma;
1118*58da3067SDavid du Colombier ulong t;
11197dd7cddfSDavid du Colombier
11208ccd4a63SDavid du Colombier USED(op);
11217dd7cddfSDavid du Colombier obdst = bdst;
11228ccd4a63SDavid du Colombier
11237dd7cddfSDavid du Colombier for(i=0; i<dx; i++){
11247dd7cddfSDavid du Colombier ma = *bmask.alpha;
11258ccd4a63SDavid du Colombier fd = 255-ma;
11267dd7cddfSDavid du Colombier
11277dd7cddfSDavid du Colombier if(grey){
1128*58da3067SDavid du Colombier *bdst.grey = CALC12(ma, *bsrc.grey, fd, *bdst.grey, t);
11298ccd4a63SDavid du Colombier bsrc.grey += bsrc.delta;
11308ccd4a63SDavid du Colombier bdst.grey += bdst.delta;
11318ccd4a63SDavid du Colombier }else{
1132*58da3067SDavid du Colombier *bdst.red = CALC12(ma, *bsrc.red, fd, *bdst.red, t);
1133*58da3067SDavid du Colombier *bdst.grn = CALC12(ma, *bsrc.grn, fd, *bdst.grn, t);
1134*58da3067SDavid du Colombier *bdst.blu = CALC12(ma, *bsrc.blu, fd, *bdst.blu, t);
11358ccd4a63SDavid du Colombier bsrc.red += bsrc.delta;
11368ccd4a63SDavid du Colombier bsrc.blu += bsrc.delta;
11378ccd4a63SDavid du Colombier bsrc.grn += bsrc.delta;
11388ccd4a63SDavid du Colombier bdst.red += bdst.delta;
11398ccd4a63SDavid du Colombier bdst.blu += bdst.delta;
11408ccd4a63SDavid du Colombier bdst.grn += bdst.delta;
11418ccd4a63SDavid du Colombier }
11428ccd4a63SDavid du Colombier if(bdst.alpha != &ones){
1143*58da3067SDavid du Colombier *bdst.alpha = ma+CALC11(fd, *bdst.alpha, t);
11448ccd4a63SDavid du Colombier bdst.alpha += bdst.delta;
11458ccd4a63SDavid du Colombier }
11468ccd4a63SDavid du Colombier bmask.alpha += bmask.delta;
11478ccd4a63SDavid du Colombier }
11488ccd4a63SDavid du Colombier return obdst;
11498ccd4a63SDavid du Colombier }
11508ccd4a63SDavid du Colombier
11518ccd4a63SDavid du Colombier static Buffer
boolcalc14(Buffer bdst,Buffer b1,Buffer bmask,int dx,int grey,int op)11528ccd4a63SDavid du Colombier boolcalc14(Buffer bdst, Buffer b1, Buffer bmask, int dx, int grey, int op)
11538ccd4a63SDavid du Colombier {
11548ccd4a63SDavid du Colombier Buffer obdst;
11558ccd4a63SDavid du Colombier int i, ma, zero;
11568ccd4a63SDavid du Colombier
11578ccd4a63SDavid du Colombier obdst = bdst;
11588ccd4a63SDavid du Colombier
11598ccd4a63SDavid du Colombier for(i=0; i<dx; i++){
11608ccd4a63SDavid du Colombier ma = *bmask.alpha;
11618ccd4a63SDavid du Colombier zero = ma ? op == DoutS : op == DinS;
11628ccd4a63SDavid du Colombier
11638ccd4a63SDavid du Colombier if(grey){
11648ccd4a63SDavid du Colombier if(zero)
11658ccd4a63SDavid du Colombier *bdst.grey = 0;
11668ccd4a63SDavid du Colombier bdst.grey += bdst.delta;
11678ccd4a63SDavid du Colombier }else{
11688ccd4a63SDavid du Colombier if(zero)
11698ccd4a63SDavid du Colombier *bdst.red = *bdst.grn = *bdst.blu = 0;
11708ccd4a63SDavid du Colombier bdst.red += bdst.delta;
11718ccd4a63SDavid du Colombier bdst.blu += bdst.delta;
11728ccd4a63SDavid du Colombier bdst.grn += bdst.delta;
11738ccd4a63SDavid du Colombier }
11748ccd4a63SDavid du Colombier bmask.alpha += bmask.delta;
11758ccd4a63SDavid du Colombier if(bdst.alpha != &ones){
11768ccd4a63SDavid du Colombier if(zero)
11778ccd4a63SDavid du Colombier *bdst.alpha = 0;
11788ccd4a63SDavid du Colombier bdst.alpha += bdst.delta;
11798ccd4a63SDavid du Colombier }
11808ccd4a63SDavid du Colombier }
11818ccd4a63SDavid du Colombier return obdst;
11828ccd4a63SDavid du Colombier }
11838ccd4a63SDavid du Colombier
11848ccd4a63SDavid du Colombier static Buffer
boolcalc236789(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)11858ccd4a63SDavid du Colombier boolcalc236789(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
11868ccd4a63SDavid du Colombier {
11878ccd4a63SDavid du Colombier Buffer obdst;
11888ccd4a63SDavid du Colombier int fs, fd;
11898ccd4a63SDavid du Colombier int i, ma, da, zero;
1190*58da3067SDavid du Colombier ulong t;
11918ccd4a63SDavid du Colombier
11928ccd4a63SDavid du Colombier obdst = bdst;
11938ccd4a63SDavid du Colombier zero = !(op&1);
11948ccd4a63SDavid du Colombier
11958ccd4a63SDavid du Colombier for(i=0; i<dx; i++){
11968ccd4a63SDavid du Colombier ma = *bmask.alpha;
11978ccd4a63SDavid du Colombier da = *bdst.alpha;
11988ccd4a63SDavid du Colombier fs = da;
11998ccd4a63SDavid du Colombier if(op&2)
12008ccd4a63SDavid du Colombier fs = 255-da;
12018ccd4a63SDavid du Colombier fd = 0;
12028ccd4a63SDavid du Colombier if(op&4)
12038ccd4a63SDavid du Colombier fd = 255;
12048ccd4a63SDavid du Colombier
12058ccd4a63SDavid du Colombier if(grey){
12067dd7cddfSDavid du Colombier if(ma)
1207*58da3067SDavid du Colombier *bdst.grey = CALC12(fs, *bsrc.grey, fd, *bdst.grey, t);
12088ccd4a63SDavid du Colombier else if(zero)
12098ccd4a63SDavid du Colombier *bdst.grey = 0;
12107dd7cddfSDavid du Colombier bsrc.grey += bsrc.delta;
12117dd7cddfSDavid du Colombier bdst.grey += bdst.delta;
12127dd7cddfSDavid du Colombier }else{
12137dd7cddfSDavid du Colombier if(ma){
1214*58da3067SDavid du Colombier *bdst.red = CALC12(fs, *bsrc.red, fd, *bdst.red, t);
1215*58da3067SDavid du Colombier *bdst.grn = CALC12(fs, *bsrc.grn, fd, *bdst.grn, t);
1216*58da3067SDavid du Colombier *bdst.blu = CALC12(fs, *bsrc.blu, fd, *bdst.blu, t);
12177dd7cddfSDavid du Colombier }
12188ccd4a63SDavid du Colombier else if(zero)
12198ccd4a63SDavid du Colombier *bdst.red = *bdst.grn = *bdst.blu = 0;
12207dd7cddfSDavid du Colombier bsrc.red += bsrc.delta;
12217dd7cddfSDavid du Colombier bsrc.blu += bsrc.delta;
12227dd7cddfSDavid du Colombier bsrc.grn += bsrc.delta;
12237dd7cddfSDavid du Colombier bdst.red += bdst.delta;
12247dd7cddfSDavid du Colombier bdst.blu += bdst.delta;
12257dd7cddfSDavid du Colombier bdst.grn += bdst.delta;
12267dd7cddfSDavid du Colombier }
12277dd7cddfSDavid du Colombier bmask.alpha += bmask.delta;
12288ccd4a63SDavid du Colombier if(bdst.alpha != &ones){
12297dd7cddfSDavid du Colombier if(ma)
1230*58da3067SDavid du Colombier *bdst.alpha = fs+CALC11(fd, da, t);
12318ccd4a63SDavid du Colombier else if(zero)
12328ccd4a63SDavid du Colombier *bdst.alpha = 0;
12337dd7cddfSDavid du Colombier bdst.alpha += bdst.delta;
12347dd7cddfSDavid du Colombier }
12357dd7cddfSDavid du Colombier }
12367dd7cddfSDavid du Colombier return obdst;
12377dd7cddfSDavid du Colombier }
12387dd7cddfSDavid du Colombier
12398ccd4a63SDavid du Colombier static Buffer
boolcalc1011(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int grey,int op)12408ccd4a63SDavid du Colombier boolcalc1011(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op)
12418ccd4a63SDavid du Colombier {
12428ccd4a63SDavid du Colombier Buffer obdst;
12438ccd4a63SDavid du Colombier int i, ma, zero;
12448ccd4a63SDavid du Colombier
12458ccd4a63SDavid du Colombier obdst = bdst;
12468ccd4a63SDavid du Colombier zero = !(op&1);
12478ccd4a63SDavid du Colombier
12488ccd4a63SDavid du Colombier for(i=0; i<dx; i++){
12498ccd4a63SDavid du Colombier ma = *bmask.alpha;
12508ccd4a63SDavid du Colombier
12518ccd4a63SDavid du Colombier if(grey){
12528ccd4a63SDavid du Colombier if(ma)
12538ccd4a63SDavid du Colombier *bdst.grey = *bsrc.grey;
12548ccd4a63SDavid du Colombier else if(zero)
12558ccd4a63SDavid du Colombier *bdst.grey = 0;
12568ccd4a63SDavid du Colombier bsrc.grey += bsrc.delta;
12578ccd4a63SDavid du Colombier bdst.grey += bdst.delta;
12588ccd4a63SDavid du Colombier }else{
12598ccd4a63SDavid du Colombier if(ma){
12608ccd4a63SDavid du Colombier *bdst.red = *bsrc.red;
12618ccd4a63SDavid du Colombier *bdst.grn = *bsrc.grn;
12628ccd4a63SDavid du Colombier *bdst.blu = *bsrc.blu;
12638ccd4a63SDavid du Colombier }
12648ccd4a63SDavid du Colombier else if(zero)
12658ccd4a63SDavid du Colombier *bdst.red = *bdst.grn = *bdst.blu = 0;
12668ccd4a63SDavid du Colombier bsrc.red += bsrc.delta;
12678ccd4a63SDavid du Colombier bsrc.blu += bsrc.delta;
12688ccd4a63SDavid du Colombier bsrc.grn += bsrc.delta;
12698ccd4a63SDavid du Colombier bdst.red += bdst.delta;
12708ccd4a63SDavid du Colombier bdst.blu += bdst.delta;
12718ccd4a63SDavid du Colombier bdst.grn += bdst.delta;
12728ccd4a63SDavid du Colombier }
12738ccd4a63SDavid du Colombier bmask.alpha += bmask.delta;
12748ccd4a63SDavid du Colombier if(bdst.alpha != &ones){
12758ccd4a63SDavid du Colombier if(ma)
12768ccd4a63SDavid du Colombier *bdst.alpha = 255;
12778ccd4a63SDavid du Colombier else if(zero)
12788ccd4a63SDavid du Colombier *bdst.alpha = 0;
12798ccd4a63SDavid du Colombier bdst.alpha += bdst.delta;
12808ccd4a63SDavid du Colombier }
12818ccd4a63SDavid du Colombier }
12828ccd4a63SDavid du Colombier return obdst;
12838ccd4a63SDavid du Colombier }
12847dd7cddfSDavid du Colombier /*
12857dd7cddfSDavid du Colombier * Replicated cached scan line read. Call the function listed in the Param,
12867dd7cddfSDavid du Colombier * but cache the result so that for replicated images we only do the work once.
12877dd7cddfSDavid du Colombier */
12887dd7cddfSDavid du Colombier static Buffer
replread(Param * p,uchar * s,int y)12898ccd4a63SDavid du Colombier replread(Param *p, uchar *s, int y)
12907dd7cddfSDavid du Colombier {
12917dd7cddfSDavid du Colombier Buffer *b;
12927dd7cddfSDavid du Colombier
12938ccd4a63SDavid du Colombier USED(s);
12947dd7cddfSDavid du Colombier b = &p->bcache[y];
12957dd7cddfSDavid du Colombier if((p->bfilled & (1<<y)) == 0){
12967dd7cddfSDavid du Colombier p->bfilled |= 1<<y;
12977dd7cddfSDavid du Colombier *b = p->replcall(p, p->bufbase+y*p->bufdelta, y);
12987dd7cddfSDavid du Colombier }
12997dd7cddfSDavid du Colombier return *b;
13007dd7cddfSDavid du Colombier }
13017dd7cddfSDavid du Colombier
13027dd7cddfSDavid du Colombier /*
13037dd7cddfSDavid du Colombier * Alpha reading function that simply relabels the grey pointer.
13047dd7cddfSDavid du Colombier */
13057dd7cddfSDavid du Colombier static Buffer
greymaskread(Param * p,uchar * buf,int y)13067dd7cddfSDavid du Colombier greymaskread(Param *p, uchar *buf, int y)
13077dd7cddfSDavid du Colombier {
13087dd7cddfSDavid du Colombier Buffer b;
13097dd7cddfSDavid du Colombier
13107dd7cddfSDavid du Colombier b = p->greymaskcall(p, buf, y);
13117dd7cddfSDavid du Colombier b.alpha = b.grey;
13127dd7cddfSDavid du Colombier return b;
13137dd7cddfSDavid du Colombier }
13147dd7cddfSDavid du Colombier
13157dd7cddfSDavid du Colombier #define DBG if(0)
13167dd7cddfSDavid du Colombier static Buffer
readnbit(Param * p,uchar * buf,int y)13177dd7cddfSDavid du Colombier readnbit(Param *p, uchar *buf, int y)
13187dd7cddfSDavid du Colombier {
13197dd7cddfSDavid du Colombier Buffer b;
13207dd7cddfSDavid du Colombier Memimage *img;
13217dd7cddfSDavid du Colombier uchar *repl, *r, *w, *ow, bits;
13227dd7cddfSDavid du Colombier int i, n, sh, depth, x, dx, npack, nbits;
13237dd7cddfSDavid du Colombier
13248ccd4a63SDavid du Colombier b.rgba = (ulong*)buf;
13257dd7cddfSDavid du Colombier b.grey = w = buf;
13267dd7cddfSDavid du Colombier b.red = b.blu = b.grn = w;
13278ccd4a63SDavid du Colombier b.alpha = &ones;
13287dd7cddfSDavid du Colombier b.delta = 1;
13297dd7cddfSDavid du Colombier
13307dd7cddfSDavid du Colombier dx = p->dx;
13317dd7cddfSDavid du Colombier img = p->img;
13327dd7cddfSDavid du Colombier depth = img->depth;
13337dd7cddfSDavid du Colombier repl = &replbit[depth][0];
13347dd7cddfSDavid du Colombier npack = 8/depth;
13357dd7cddfSDavid du Colombier sh = 8-depth;
13367dd7cddfSDavid du Colombier
13377dd7cddfSDavid du Colombier /* copy from p->r.min.x until end of repl rectangle */
13387dd7cddfSDavid du Colombier x = p->r.min.x;
13397dd7cddfSDavid du Colombier n = dx;
13407dd7cddfSDavid du Colombier if(n > p->img->r.max.x - x)
13417dd7cddfSDavid du Colombier n = p->img->r.max.x - x;
13427dd7cddfSDavid du Colombier
13437dd7cddfSDavid du Colombier r = p->bytermin + y*p->bwidth;
13447dd7cddfSDavid du Colombier DBG print("readnbit dx %d %p=%p+%d*%d, *r=%d fetch %d ", dx, r, p->bytermin, y, p->bwidth, *r, n);
13457dd7cddfSDavid du Colombier bits = *r++;
13467dd7cddfSDavid du Colombier nbits = 8;
13478ccd4a63SDavid du Colombier if((i=x&(npack-1))){
13487dd7cddfSDavid du Colombier DBG print("throwaway %d...", i);
13497dd7cddfSDavid du Colombier bits <<= depth*i;
13507dd7cddfSDavid du Colombier nbits -= depth*i;
13517dd7cddfSDavid du Colombier }
13527dd7cddfSDavid du Colombier for(i=0; i<n; i++){
13537dd7cddfSDavid du Colombier if(nbits == 0){
13547dd7cddfSDavid du Colombier DBG print("(%.2ux)...", *r);
13557dd7cddfSDavid du Colombier bits = *r++;
13567dd7cddfSDavid du Colombier nbits = 8;
13577dd7cddfSDavid du Colombier }
13587dd7cddfSDavid du Colombier *w++ = repl[bits>>sh];
13597dd7cddfSDavid du Colombier DBG print("bit %x...", repl[bits>>sh]);
13607dd7cddfSDavid du Colombier bits <<= depth;
13617dd7cddfSDavid du Colombier nbits -= depth;
13627dd7cddfSDavid du Colombier }
13637dd7cddfSDavid du Colombier dx -= n;
13647dd7cddfSDavid du Colombier if(dx == 0)
13657dd7cddfSDavid du Colombier return b;
13667dd7cddfSDavid du Colombier
13677dd7cddfSDavid du Colombier assert(x+i == p->img->r.max.x);
13687dd7cddfSDavid du Colombier
13697dd7cddfSDavid du Colombier /* copy from beginning of repl rectangle until where we were before. */
13707dd7cddfSDavid du Colombier x = p->img->r.min.x;
13717dd7cddfSDavid du Colombier n = dx;
13727dd7cddfSDavid du Colombier if(n > p->r.min.x - x)
13737dd7cddfSDavid du Colombier n = p->r.min.x - x;
13747dd7cddfSDavid du Colombier
13757dd7cddfSDavid du Colombier r = p->bytey0s + y*p->bwidth;
13767dd7cddfSDavid du Colombier DBG print("x=%d r=%p...", x, r);
13777dd7cddfSDavid du Colombier bits = *r++;
13787dd7cddfSDavid du Colombier nbits = 8;
13798ccd4a63SDavid du Colombier if((i=x&(npack-1))){
13807dd7cddfSDavid du Colombier bits <<= depth*i;
13817dd7cddfSDavid du Colombier nbits -= depth*i;
13827dd7cddfSDavid du Colombier }
13837dd7cddfSDavid du Colombier DBG print("nbits=%d...", nbits);
13847dd7cddfSDavid du Colombier for(i=0; i<n; i++){
13857dd7cddfSDavid du Colombier if(nbits == 0){
13867dd7cddfSDavid du Colombier bits = *r++;
13877dd7cddfSDavid du Colombier nbits = 8;
13887dd7cddfSDavid du Colombier }
13897dd7cddfSDavid du Colombier *w++ = repl[bits>>sh];
13907dd7cddfSDavid du Colombier DBG print("bit %x...", repl[bits>>sh]);
13917dd7cddfSDavid du Colombier bits <<= depth;
13927dd7cddfSDavid du Colombier nbits -= depth;
13937dd7cddfSDavid du Colombier DBG print("bits %x nbits %d...", bits, nbits);
13947dd7cddfSDavid du Colombier }
13957dd7cddfSDavid du Colombier dx -= n;
13967dd7cddfSDavid du Colombier if(dx == 0)
13977dd7cddfSDavid du Colombier return b;
13987dd7cddfSDavid du Colombier
13997dd7cddfSDavid du Colombier assert(dx > 0);
14007dd7cddfSDavid du Colombier /* now we have exactly one full scan line: just replicate the buffer itself until we are done */
14017dd7cddfSDavid du Colombier ow = buf;
14027dd7cddfSDavid du Colombier while(dx--)
14037dd7cddfSDavid du Colombier *w++ = *ow++;
14047dd7cddfSDavid du Colombier
14057dd7cddfSDavid du Colombier return b;
14067dd7cddfSDavid du Colombier }
14077dd7cddfSDavid du Colombier #undef DBG
14087dd7cddfSDavid du Colombier
14097dd7cddfSDavid du Colombier #define DBG if(0)
14107dd7cddfSDavid du Colombier static void
writenbit(Param * p,uchar * w,Buffer src)14117dd7cddfSDavid du Colombier writenbit(Param *p, uchar *w, Buffer src)
14127dd7cddfSDavid du Colombier {
14137dd7cddfSDavid du Colombier uchar *r;
14147dd7cddfSDavid du Colombier ulong bits;
14157dd7cddfSDavid du Colombier int i, sh, depth, npack, nbits, x, ex;
14167dd7cddfSDavid du Colombier
14177dd7cddfSDavid du Colombier assert(src.grey != nil && src.delta == 1);
14187dd7cddfSDavid du Colombier
14197dd7cddfSDavid du Colombier x = p->r.min.x;
14207dd7cddfSDavid du Colombier ex = x+p->dx;
14217dd7cddfSDavid du Colombier depth = p->img->depth;
14227dd7cddfSDavid du Colombier npack = 8/depth;
14237dd7cddfSDavid du Colombier
14247dd7cddfSDavid du Colombier i=x&(npack-1);
14257dd7cddfSDavid du Colombier bits = i ? (*w >> (8-depth*i)) : 0;
14267dd7cddfSDavid du Colombier nbits = depth*i;
14277dd7cddfSDavid du Colombier sh = 8-depth;
14287dd7cddfSDavid du Colombier r = src.grey;
14297dd7cddfSDavid du Colombier
14307dd7cddfSDavid du Colombier for(; x<ex; x++){
14317dd7cddfSDavid du Colombier bits <<= depth;
14327dd7cddfSDavid du Colombier DBG print(" %x", *r);
14337dd7cddfSDavid du Colombier bits |= (*r++ >> sh);
14347dd7cddfSDavid du Colombier nbits += depth;
14357dd7cddfSDavid du Colombier if(nbits == 8){
14367dd7cddfSDavid du Colombier *w++ = bits;
14377dd7cddfSDavid du Colombier nbits = 0;
14387dd7cddfSDavid du Colombier }
14397dd7cddfSDavid du Colombier }
14407dd7cddfSDavid du Colombier
14417dd7cddfSDavid du Colombier if(nbits){
14427dd7cddfSDavid du Colombier sh = 8-nbits;
14437dd7cddfSDavid du Colombier bits <<= sh;
14447dd7cddfSDavid du Colombier bits |= *w & ((1<<sh)-1);
14457dd7cddfSDavid du Colombier *w = bits;
14467dd7cddfSDavid du Colombier }
14477dd7cddfSDavid du Colombier DBG print("\n");
14487dd7cddfSDavid du Colombier return;
14497dd7cddfSDavid du Colombier }
14507dd7cddfSDavid du Colombier #undef DBG
14517dd7cddfSDavid du Colombier
14527dd7cddfSDavid du Colombier static Buffer
readcmap(Param * p,uchar * buf,int y)14537dd7cddfSDavid du Colombier readcmap(Param *p, uchar *buf, int y)
14547dd7cddfSDavid du Colombier {
14557dd7cddfSDavid du Colombier Buffer b;
14568ccd4a63SDavid du Colombier int a, convgrey, copyalpha, dx, i, m;
14577dd7cddfSDavid du Colombier uchar *q, *cmap, *begin, *end, *r, *w;
14587dd7cddfSDavid du Colombier
14597dd7cddfSDavid du Colombier begin = p->bytey0s + y*p->bwidth;
14607dd7cddfSDavid du Colombier r = p->bytermin + y*p->bwidth;
14617dd7cddfSDavid du Colombier end = p->bytey0e + y*p->bwidth;
14627dd7cddfSDavid du Colombier cmap = p->img->cmap->cmap2rgb;
14637dd7cddfSDavid du Colombier convgrey = p->convgrey;
14648ccd4a63SDavid du Colombier copyalpha = (p->img->flags&Falpha) ? 1 : 0;
14657dd7cddfSDavid du Colombier
14667dd7cddfSDavid du Colombier w = buf;
14677dd7cddfSDavid du Colombier dx = p->dx;
14688ccd4a63SDavid du Colombier if(copyalpha){
14698ccd4a63SDavid du Colombier b.alpha = buf++;
14708ccd4a63SDavid du Colombier a = p->img->shift[CAlpha]/8;
14718ccd4a63SDavid du Colombier m = p->img->shift[CMap]/8;
14728ccd4a63SDavid du Colombier for(i=0; i<dx; i++){
14738ccd4a63SDavid du Colombier *w++ = r[a];
14748ccd4a63SDavid du Colombier q = cmap+r[m]*3;
14758ccd4a63SDavid du Colombier r += 2;
14768ccd4a63SDavid du Colombier if(r == end)
14778ccd4a63SDavid du Colombier r = begin;
14788ccd4a63SDavid du Colombier if(convgrey){
14798ccd4a63SDavid du Colombier *w++ = RGB2K(q[0], q[1], q[2]);
14808ccd4a63SDavid du Colombier }else{
14818ccd4a63SDavid du Colombier *w++ = q[2]; /* blue */
14828ccd4a63SDavid du Colombier *w++ = q[1]; /* green */
14838ccd4a63SDavid du Colombier *w++ = q[0]; /* red */
14848ccd4a63SDavid du Colombier }
14858ccd4a63SDavid du Colombier }
14868ccd4a63SDavid du Colombier }else{
14878ccd4a63SDavid du Colombier b.alpha = &ones;
14887dd7cddfSDavid du Colombier for(i=0; i<dx; i++){
14897dd7cddfSDavid du Colombier q = cmap+*r++*3;
14907dd7cddfSDavid du Colombier if(r == end)
14917dd7cddfSDavid du Colombier r = begin;
14927dd7cddfSDavid du Colombier if(convgrey){
14937dd7cddfSDavid du Colombier *w++ = RGB2K(q[0], q[1], q[2]);
14947dd7cddfSDavid du Colombier }else{
14957dd7cddfSDavid du Colombier *w++ = q[2]; /* blue */
14967dd7cddfSDavid du Colombier *w++ = q[1]; /* green */
14977dd7cddfSDavid du Colombier *w++ = q[0]; /* red */
14987dd7cddfSDavid du Colombier }
14997dd7cddfSDavid du Colombier }
15008ccd4a63SDavid du Colombier }
15018ccd4a63SDavid du Colombier
15028ccd4a63SDavid du Colombier b.rgba = (ulong*)(buf-copyalpha);
15037dd7cddfSDavid du Colombier
15047dd7cddfSDavid du Colombier if(convgrey){
15057dd7cddfSDavid du Colombier b.grey = buf;
15067dd7cddfSDavid du Colombier b.red = b.blu = b.grn = buf;
15078ccd4a63SDavid du Colombier b.delta = 1+copyalpha;
15087dd7cddfSDavid du Colombier }else{
15097dd7cddfSDavid du Colombier b.blu = buf;
15107dd7cddfSDavid du Colombier b.grn = buf+1;
15117dd7cddfSDavid du Colombier b.red = buf+2;
15127dd7cddfSDavid du Colombier b.grey = nil;
15138ccd4a63SDavid du Colombier b.delta = 3+copyalpha;
15147dd7cddfSDavid du Colombier }
15157dd7cddfSDavid du Colombier return b;
15167dd7cddfSDavid du Colombier }
15177dd7cddfSDavid du Colombier
15187dd7cddfSDavid du Colombier static void
writecmap(Param * p,uchar * w,Buffer src)15197dd7cddfSDavid du Colombier writecmap(Param *p, uchar *w, Buffer src)
15207dd7cddfSDavid du Colombier {
15217dd7cddfSDavid du Colombier uchar *cmap, *red, *grn, *blu;
15227dd7cddfSDavid du Colombier int i, dx, delta;
15237dd7cddfSDavid du Colombier
15247dd7cddfSDavid du Colombier cmap = p->img->cmap->rgb2cmap;
15257dd7cddfSDavid du Colombier
15267dd7cddfSDavid du Colombier delta = src.delta;
15277dd7cddfSDavid du Colombier red= src.red;
15287dd7cddfSDavid du Colombier grn = src.grn;
15297dd7cddfSDavid du Colombier blu = src.blu;
15307dd7cddfSDavid du Colombier
15317dd7cddfSDavid du Colombier dx = p->dx;
15327dd7cddfSDavid du Colombier for(i=0; i<dx; i++, red+=delta, grn+=delta, blu+=delta)
15337dd7cddfSDavid du Colombier *w++ = cmap[(*red>>4)*256+(*grn>>4)*16+(*blu>>4)];
15347dd7cddfSDavid du Colombier }
15357dd7cddfSDavid du Colombier
15368ccd4a63SDavid du Colombier #define DBG if(0)
15377dd7cddfSDavid du Colombier static Buffer
readbyte(Param * p,uchar * buf,int y)15387dd7cddfSDavid du Colombier readbyte(Param *p, uchar *buf, int y)
15397dd7cddfSDavid du Colombier {
15407dd7cddfSDavid du Colombier Buffer b;
15417dd7cddfSDavid du Colombier Memimage *img;
15427dd7cddfSDavid du Colombier int dx, isgrey, convgrey, alphaonly, copyalpha, i, nb;
15437dd7cddfSDavid du Colombier uchar *begin, *end, *r, *w, *rrepl, *grepl, *brepl, *arepl, *krepl;
15447dd7cddfSDavid du Colombier uchar ured, ugrn, ublu;
15457dd7cddfSDavid du Colombier ulong u;
15467dd7cddfSDavid du Colombier
15477dd7cddfSDavid du Colombier img = p->img;
15487dd7cddfSDavid du Colombier begin = p->bytey0s + y*p->bwidth;
15497dd7cddfSDavid du Colombier r = p->bytermin + y*p->bwidth;
15507dd7cddfSDavid du Colombier end = p->bytey0e + y*p->bwidth;
15517dd7cddfSDavid du Colombier
15527dd7cddfSDavid du Colombier w = buf;
15537dd7cddfSDavid du Colombier dx = p->dx;
15547dd7cddfSDavid du Colombier nb = img->depth/8;
15557dd7cddfSDavid du Colombier
15567dd7cddfSDavid du Colombier convgrey = p->convgrey; /* convert rgb to grey */
15577dd7cddfSDavid du Colombier isgrey = img->flags&Fgrey;
15587dd7cddfSDavid du Colombier alphaonly = p->alphaonly;
155959cc4ca5SDavid du Colombier copyalpha = (img->flags&Falpha) ? 1 : 0;
15607dd7cddfSDavid du Colombier
15618ccd4a63SDavid du Colombier DBG print("copyalpha %d alphaonly %d convgrey %d isgrey %d\n", copyalpha, alphaonly, convgrey, isgrey);
15627dd7cddfSDavid du Colombier /* if we can, avoid processing everything */
15637dd7cddfSDavid du Colombier if(!(img->flags&Frepl) && !convgrey && (img->flags&Fbytes)){
15647dd7cddfSDavid du Colombier memset(&b, 0, sizeof b);
15657dd7cddfSDavid du Colombier if(p->needbuf){
15667dd7cddfSDavid du Colombier memmove(buf, r, dx*nb);
15677dd7cddfSDavid du Colombier r = buf;
15687dd7cddfSDavid du Colombier }
15698ccd4a63SDavid du Colombier b.rgba = (ulong*)r;
15707dd7cddfSDavid du Colombier if(copyalpha)
15717dd7cddfSDavid du Colombier b.alpha = r+img->shift[CAlpha]/8;
15728ccd4a63SDavid du Colombier else
15738ccd4a63SDavid du Colombier b.alpha = &ones;
15747dd7cddfSDavid du Colombier if(isgrey){
15757dd7cddfSDavid du Colombier b.grey = r+img->shift[CGrey]/8;
15767dd7cddfSDavid du Colombier b.red = b.grn = b.blu = b.grey;
15777dd7cddfSDavid du Colombier }else{
15787dd7cddfSDavid du Colombier b.red = r+img->shift[CRed]/8;
15797dd7cddfSDavid du Colombier b.grn = r+img->shift[CGreen]/8;
15807dd7cddfSDavid du Colombier b.blu = r+img->shift[CBlue]/8;
15817dd7cddfSDavid du Colombier }
15827dd7cddfSDavid du Colombier b.delta = nb;
15837dd7cddfSDavid du Colombier return b;
15847dd7cddfSDavid du Colombier }
15857dd7cddfSDavid du Colombier
15868ccd4a63SDavid du Colombier DBG print("2\n");
15877dd7cddfSDavid du Colombier rrepl = replbit[img->nbits[CRed]];
15887dd7cddfSDavid du Colombier grepl = replbit[img->nbits[CGreen]];
15897dd7cddfSDavid du Colombier brepl = replbit[img->nbits[CBlue]];
15907dd7cddfSDavid du Colombier arepl = replbit[img->nbits[CAlpha]];
15917dd7cddfSDavid du Colombier krepl = replbit[img->nbits[CGrey]];
15927dd7cddfSDavid du Colombier
15937dd7cddfSDavid du Colombier for(i=0; i<dx; i++){
15947dd7cddfSDavid du Colombier u = r[0] | (r[1]<<8) | (r[2]<<16) | (r[3]<<24);
15958ccd4a63SDavid du Colombier if(copyalpha) {
15967dd7cddfSDavid du Colombier *w++ = arepl[(u>>img->shift[CAlpha]) & img->mask[CAlpha]];
15978ccd4a63SDavid du Colombier DBG print("a %x\n", w[-1]);
15988ccd4a63SDavid du Colombier }
15997dd7cddfSDavid du Colombier
16007dd7cddfSDavid du Colombier if(isgrey)
16017dd7cddfSDavid du Colombier *w++ = krepl[(u >> img->shift[CGrey]) & img->mask[CGrey]];
16027dd7cddfSDavid du Colombier else if(!alphaonly){
16037dd7cddfSDavid du Colombier ured = rrepl[(u >> img->shift[CRed]) & img->mask[CRed]];
16047dd7cddfSDavid du Colombier ugrn = grepl[(u >> img->shift[CGreen]) & img->mask[CGreen]];
16057dd7cddfSDavid du Colombier ublu = brepl[(u >> img->shift[CBlue]) & img->mask[CBlue]];
16067dd7cddfSDavid du Colombier if(convgrey){
16078ccd4a63SDavid du Colombier DBG print("g %x %x %x\n", ured, ugrn, ublu);
16087dd7cddfSDavid du Colombier *w++ = RGB2K(ured, ugrn, ublu);
16098ccd4a63SDavid du Colombier DBG print("%x\n", w[-1]);
16107dd7cddfSDavid du Colombier }else{
16117dd7cddfSDavid du Colombier *w++ = brepl[(u >> img->shift[CBlue]) & img->mask[CBlue]];
16127dd7cddfSDavid du Colombier *w++ = grepl[(u >> img->shift[CGreen]) & img->mask[CGreen]];
16137dd7cddfSDavid du Colombier *w++ = rrepl[(u >> img->shift[CRed]) & img->mask[CRed]];
16147dd7cddfSDavid du Colombier }
16157dd7cddfSDavid du Colombier }
16167dd7cddfSDavid du Colombier r += nb;
16177dd7cddfSDavid du Colombier if(r == end)
16187dd7cddfSDavid du Colombier r = begin;
16197dd7cddfSDavid du Colombier }
16207dd7cddfSDavid du Colombier
16218ccd4a63SDavid du Colombier b.alpha = copyalpha ? buf : &ones;
16228ccd4a63SDavid du Colombier b.rgba = (ulong*)buf;
16237dd7cddfSDavid du Colombier if(alphaonly){
16247dd7cddfSDavid du Colombier b.red = b.grn = b.blu = b.grey = nil;
16258ccd4a63SDavid du Colombier if(!copyalpha)
16268ccd4a63SDavid du Colombier b.rgba = nil;
16277dd7cddfSDavid du Colombier b.delta = 1;
16287dd7cddfSDavid du Colombier }else if(isgrey || convgrey){
16297dd7cddfSDavid du Colombier b.grey = buf+copyalpha;
16307dd7cddfSDavid du Colombier b.red = b.grn = b.blu = buf+copyalpha;
16317dd7cddfSDavid du Colombier b.delta = copyalpha+1;
16328ccd4a63SDavid du Colombier DBG print("alpha %x grey %x\n", b.alpha ? *b.alpha : 0xFF, *b.grey);
16337dd7cddfSDavid du Colombier }else{
16347dd7cddfSDavid du Colombier b.blu = buf+copyalpha;
16357dd7cddfSDavid du Colombier b.grn = buf+copyalpha+1;
16367dd7cddfSDavid du Colombier b.grey = nil;
16377dd7cddfSDavid du Colombier b.red = buf+copyalpha+2;
16387dd7cddfSDavid du Colombier b.delta = copyalpha+3;
16397dd7cddfSDavid du Colombier }
16407dd7cddfSDavid du Colombier return b;
16417dd7cddfSDavid du Colombier }
16428ccd4a63SDavid du Colombier #undef DBG
16437dd7cddfSDavid du Colombier
16447dd7cddfSDavid du Colombier #define DBG if(0)
16457dd7cddfSDavid du Colombier static void
writebyte(Param * p,uchar * w,Buffer src)16467dd7cddfSDavid du Colombier writebyte(Param *p, uchar *w, Buffer src)
16477dd7cddfSDavid du Colombier {
16487dd7cddfSDavid du Colombier Memimage *img;
16497dd7cddfSDavid du Colombier int i, isalpha, isgrey, nb, delta, dx, adelta;
16507dd7cddfSDavid du Colombier uchar ff, *red, *grn, *blu, *grey, *alpha;
16517dd7cddfSDavid du Colombier ulong u, mask;
16527dd7cddfSDavid du Colombier
16537dd7cddfSDavid du Colombier img = p->img;
16547dd7cddfSDavid du Colombier
16557dd7cddfSDavid du Colombier red = src.red;
16567dd7cddfSDavid du Colombier grn = src.grn;
16577dd7cddfSDavid du Colombier blu = src.blu;
16587dd7cddfSDavid du Colombier alpha = src.alpha;
16597dd7cddfSDavid du Colombier delta = src.delta;
16607dd7cddfSDavid du Colombier grey = src.grey;
16617dd7cddfSDavid du Colombier dx = p->dx;
16627dd7cddfSDavid du Colombier
16637dd7cddfSDavid du Colombier nb = img->depth/8;
16647dd7cddfSDavid du Colombier mask = (nb==4) ? 0 : ~((1<<img->depth)-1);
16657dd7cddfSDavid du Colombier
16667dd7cddfSDavid du Colombier isalpha = img->flags&Falpha;
16677dd7cddfSDavid du Colombier isgrey = img->flags&Fgrey;
16687dd7cddfSDavid du Colombier adelta = src.delta;
16697dd7cddfSDavid du Colombier
16708ccd4a63SDavid du Colombier if(isalpha && (alpha == nil || alpha == &ones)){
16717dd7cddfSDavid du Colombier ff = 0xFF;
16727dd7cddfSDavid du Colombier alpha = &ff;
16737dd7cddfSDavid du Colombier adelta = 0;
16747dd7cddfSDavid du Colombier }
16757dd7cddfSDavid du Colombier
16767dd7cddfSDavid du Colombier for(i=0; i<dx; i++){
16777dd7cddfSDavid du Colombier u = w[0] | (w[1]<<8) | (w[2]<<16) | (w[3]<<24);
16787dd7cddfSDavid du Colombier DBG print("u %.8lux...", u);
16797dd7cddfSDavid du Colombier u &= mask;
16807dd7cddfSDavid du Colombier DBG print("&mask %.8lux...", u);
16817dd7cddfSDavid du Colombier if(isgrey){
16827dd7cddfSDavid du Colombier u |= ((*grey >> (8-img->nbits[CGrey])) & img->mask[CGrey]) << img->shift[CGrey];
16837dd7cddfSDavid du Colombier DBG print("|grey %.8lux...", u);
16847dd7cddfSDavid du Colombier grey += delta;
16857dd7cddfSDavid du Colombier }else{
16867dd7cddfSDavid du Colombier u |= ((*red >> (8-img->nbits[CRed])) & img->mask[CRed]) << img->shift[CRed];
16877dd7cddfSDavid du Colombier u |= ((*grn >> (8-img->nbits[CGreen])) & img->mask[CGreen]) << img->shift[CGreen];
16887dd7cddfSDavid du Colombier u |= ((*blu >> (8-img->nbits[CBlue])) & img->mask[CBlue]) << img->shift[CBlue];
16897dd7cddfSDavid du Colombier red += delta;
16907dd7cddfSDavid du Colombier grn += delta;
16917dd7cddfSDavid du Colombier blu += delta;
16927dd7cddfSDavid du Colombier DBG print("|rgb %.8lux...", u);
16937dd7cddfSDavid du Colombier }
16947dd7cddfSDavid du Colombier
16957dd7cddfSDavid du Colombier if(isalpha){
16967dd7cddfSDavid du Colombier u |= ((*alpha >> (8-img->nbits[CAlpha])) & img->mask[CAlpha]) << img->shift[CAlpha];
16977dd7cddfSDavid du Colombier alpha += adelta;
16987dd7cddfSDavid du Colombier DBG print("|alpha %.8lux...", u);
16997dd7cddfSDavid du Colombier }
17007dd7cddfSDavid du Colombier
17017dd7cddfSDavid du Colombier w[0] = u;
17027dd7cddfSDavid du Colombier w[1] = u>>8;
17037dd7cddfSDavid du Colombier w[2] = u>>16;
17047dd7cddfSDavid du Colombier w[3] = u>>24;
17057dd7cddfSDavid du Colombier w += nb;
17067dd7cddfSDavid du Colombier }
17077dd7cddfSDavid du Colombier }
17087dd7cddfSDavid du Colombier #undef DBG
17097dd7cddfSDavid du Colombier
17107dd7cddfSDavid du Colombier static Readfn*
readfn(Memimage * img)17117dd7cddfSDavid du Colombier readfn(Memimage *img)
17127dd7cddfSDavid du Colombier {
17137dd7cddfSDavid du Colombier if(img->depth < 8)
17147dd7cddfSDavid du Colombier return readnbit;
17158ccd4a63SDavid du Colombier if(img->nbits[CMap] == 8)
17167dd7cddfSDavid du Colombier return readcmap;
17177dd7cddfSDavid du Colombier return readbyte;
17187dd7cddfSDavid du Colombier }
17197dd7cddfSDavid du Colombier
17207dd7cddfSDavid du Colombier static Readfn*
readalphafn(Memimage * m)17218ccd4a63SDavid du Colombier readalphafn(Memimage *m)
17227dd7cddfSDavid du Colombier {
17238ccd4a63SDavid du Colombier USED(m);
17247dd7cddfSDavid du Colombier return readbyte;
17257dd7cddfSDavid du Colombier }
17267dd7cddfSDavid du Colombier
17277dd7cddfSDavid du Colombier static Writefn*
writefn(Memimage * img)17287dd7cddfSDavid du Colombier writefn(Memimage *img)
17297dd7cddfSDavid du Colombier {
17307dd7cddfSDavid du Colombier if(img->depth < 8)
17317dd7cddfSDavid du Colombier return writenbit;
17327dd7cddfSDavid du Colombier if(img->chan == CMAP8)
17337dd7cddfSDavid du Colombier return writecmap;
17347dd7cddfSDavid du Colombier return writebyte;
17357dd7cddfSDavid du Colombier }
17367dd7cddfSDavid du Colombier
17377dd7cddfSDavid du Colombier static void
nullwrite(Param * p,uchar * s,Buffer b)17388ccd4a63SDavid du Colombier nullwrite(Param *p, uchar *s, Buffer b)
17397dd7cddfSDavid du Colombier {
17408ccd4a63SDavid du Colombier USED(p);
17418ccd4a63SDavid du Colombier USED(s);
17427dd7cddfSDavid du Colombier }
17437dd7cddfSDavid du Colombier
17447dd7cddfSDavid du Colombier static Buffer
readptr(Param * p,uchar * s,int y)17458ccd4a63SDavid du Colombier readptr(Param *p, uchar *s, int y)
17467dd7cddfSDavid du Colombier {
17477dd7cddfSDavid du Colombier Buffer b;
17487dd7cddfSDavid du Colombier uchar *q;
17497dd7cddfSDavid du Colombier
17508ccd4a63SDavid du Colombier USED(s);
17517dd7cddfSDavid du Colombier q = p->bytermin + y*p->bwidth;
17527dd7cddfSDavid du Colombier b.red = q; /* ptr to data */
17537dd7cddfSDavid du Colombier b.grn = b.blu = b.grey = b.alpha = nil;
17548ccd4a63SDavid du Colombier b.rgba = (ulong*)q;
17557dd7cddfSDavid du Colombier b.delta = p->img->depth/8;
17567dd7cddfSDavid du Colombier return b;
17577dd7cddfSDavid du Colombier }
17587dd7cddfSDavid du Colombier
17597dd7cddfSDavid du Colombier static Buffer
boolmemmove(Buffer bdst,Buffer bsrc,Buffer b1,int dx,int i,int o)17608ccd4a63SDavid du Colombier boolmemmove(Buffer bdst, Buffer bsrc, Buffer b1, int dx, int i, int o)
17617dd7cddfSDavid du Colombier {
17628ccd4a63SDavid du Colombier USED(i);
17638ccd4a63SDavid du Colombier USED(o);
17647dd7cddfSDavid du Colombier memmove(bdst.red, bsrc.red, dx*bdst.delta);
17657dd7cddfSDavid du Colombier return bdst;
17667dd7cddfSDavid du Colombier }
17677dd7cddfSDavid du Colombier
17687dd7cddfSDavid du Colombier static Buffer
boolcopy8(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int i,int o)17698ccd4a63SDavid du Colombier boolcopy8(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o)
17707dd7cddfSDavid du Colombier {
17717dd7cddfSDavid du Colombier uchar *m, *r, *w, *ew;
17727dd7cddfSDavid du Colombier
17738ccd4a63SDavid du Colombier USED(i);
17748ccd4a63SDavid du Colombier USED(o);
17757dd7cddfSDavid du Colombier m = bmask.grey;
17767dd7cddfSDavid du Colombier w = bdst.red;
17777dd7cddfSDavid du Colombier r = bsrc.red;
17787dd7cddfSDavid du Colombier ew = w+dx;
17797dd7cddfSDavid du Colombier for(; w < ew; w++,r++)
17807dd7cddfSDavid du Colombier if(*m++)
17817dd7cddfSDavid du Colombier *w = *r;
17827dd7cddfSDavid du Colombier return bdst; /* not used */
17837dd7cddfSDavid du Colombier }
17847dd7cddfSDavid du Colombier
17857dd7cddfSDavid du Colombier static Buffer
boolcopy16(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int i,int o)17868ccd4a63SDavid du Colombier boolcopy16(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o)
17877dd7cddfSDavid du Colombier {
17887dd7cddfSDavid du Colombier uchar *m;
17897dd7cddfSDavid du Colombier ushort *r, *w, *ew;
17907dd7cddfSDavid du Colombier
17918ccd4a63SDavid du Colombier USED(i);
17928ccd4a63SDavid du Colombier USED(o);
17937dd7cddfSDavid du Colombier m = bmask.grey;
17947dd7cddfSDavid du Colombier w = (ushort*)bdst.red;
17957dd7cddfSDavid du Colombier r = (ushort*)bsrc.red;
17967dd7cddfSDavid du Colombier ew = w+dx;
17977dd7cddfSDavid du Colombier for(; w < ew; w++,r++)
17987dd7cddfSDavid du Colombier if(*m++)
17997dd7cddfSDavid du Colombier *w = *r;
18007dd7cddfSDavid du Colombier return bdst; /* not used */
18017dd7cddfSDavid du Colombier }
18027dd7cddfSDavid du Colombier
18037dd7cddfSDavid du Colombier static Buffer
boolcopy24(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int i,int o)18048ccd4a63SDavid du Colombier boolcopy24(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o)
18057dd7cddfSDavid du Colombier {
18067dd7cddfSDavid du Colombier uchar *m;
18077dd7cddfSDavid du Colombier uchar *r, *w, *ew;
18087dd7cddfSDavid du Colombier
18098ccd4a63SDavid du Colombier USED(i);
18108ccd4a63SDavid du Colombier USED(o);
18117dd7cddfSDavid du Colombier m = bmask.grey;
18127dd7cddfSDavid du Colombier w = bdst.red;
18137dd7cddfSDavid du Colombier r = bsrc.red;
18147dd7cddfSDavid du Colombier ew = w+dx*3;
18157dd7cddfSDavid du Colombier while(w < ew){
18167dd7cddfSDavid du Colombier if(*m++){
18177dd7cddfSDavid du Colombier *w++ = *r++;
18187dd7cddfSDavid du Colombier *w++ = *r++;
18197dd7cddfSDavid du Colombier *w++ = *r++;
18207dd7cddfSDavid du Colombier }else{
18217dd7cddfSDavid du Colombier w += 3;
18227dd7cddfSDavid du Colombier r += 3;
18237dd7cddfSDavid du Colombier }
18247dd7cddfSDavid du Colombier }
18257dd7cddfSDavid du Colombier return bdst; /* not used */
18267dd7cddfSDavid du Colombier }
18277dd7cddfSDavid du Colombier
18287dd7cddfSDavid du Colombier static Buffer
boolcopy32(Buffer bdst,Buffer bsrc,Buffer bmask,int dx,int i,int o)18298ccd4a63SDavid du Colombier boolcopy32(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int i, int o)
18307dd7cddfSDavid du Colombier {
18317dd7cddfSDavid du Colombier uchar *m;
18327dd7cddfSDavid du Colombier ulong *r, *w, *ew;
18337dd7cddfSDavid du Colombier
18348ccd4a63SDavid du Colombier USED(i);
18358ccd4a63SDavid du Colombier USED(o);
18367dd7cddfSDavid du Colombier m = bmask.grey;
18377dd7cddfSDavid du Colombier w = (ulong*)bdst.red;
18387dd7cddfSDavid du Colombier r = (ulong*)bsrc.red;
18397dd7cddfSDavid du Colombier ew = w+dx;
18407dd7cddfSDavid du Colombier for(; w < ew; w++,r++)
18417dd7cddfSDavid du Colombier if(*m++)
18427dd7cddfSDavid du Colombier *w = *r;
18437dd7cddfSDavid du Colombier return bdst; /* not used */
18447dd7cddfSDavid du Colombier }
18457dd7cddfSDavid du Colombier
18467dd7cddfSDavid du Colombier static Buffer
genconv(Param * p,uchar * buf,int y)18477dd7cddfSDavid du Colombier genconv(Param *p, uchar *buf, int y)
18487dd7cddfSDavid du Colombier {
18497dd7cddfSDavid du Colombier Buffer b;
18507dd7cddfSDavid du Colombier int nb;
18517dd7cddfSDavid du Colombier uchar *r, *w, *ew;
18527dd7cddfSDavid du Colombier
18537dd7cddfSDavid du Colombier /* read from source into RGB format in convbuf */
18547dd7cddfSDavid du Colombier b = p->convreadcall(p, p->convbuf, y);
18557dd7cddfSDavid du Colombier
18567dd7cddfSDavid du Colombier /* write RGB format into dst format in buf */
18577dd7cddfSDavid du Colombier p->convwritecall(p->convdpar, buf, b);
18587dd7cddfSDavid du Colombier
18597dd7cddfSDavid du Colombier if(p->convdx){
18607dd7cddfSDavid du Colombier nb = p->convdpar->img->depth/8;
18617dd7cddfSDavid du Colombier r = buf;
18627dd7cddfSDavid du Colombier w = buf+nb*p->dx;
18637dd7cddfSDavid du Colombier ew = buf+nb*p->convdx;
18647dd7cddfSDavid du Colombier while(w<ew)
18657dd7cddfSDavid du Colombier *w++ = *r++;
18667dd7cddfSDavid du Colombier }
18677dd7cddfSDavid du Colombier
18687dd7cddfSDavid du Colombier b.red = buf;
18697dd7cddfSDavid du Colombier b.blu = b.grn = b.grey = b.alpha = nil;
18708ccd4a63SDavid du Colombier b.rgba = (ulong*)buf;
18717dd7cddfSDavid du Colombier b.delta = 0;
18727dd7cddfSDavid du Colombier
18737dd7cddfSDavid du Colombier return b;
18747dd7cddfSDavid du Colombier }
18757dd7cddfSDavid du Colombier
18767dd7cddfSDavid du Colombier static Readfn*
convfn(Memimage * dst,Param * dpar,Memimage * src,Param * spar)18777dd7cddfSDavid du Colombier convfn(Memimage *dst, Param *dpar, Memimage *src, Param *spar)
18787dd7cddfSDavid du Colombier {
18797dd7cddfSDavid du Colombier if(dst->chan == src->chan && !(src->flags&Frepl)){
18808ccd4a63SDavid du Colombier //if(drawdebug) iprint("readptr...");
18817dd7cddfSDavid du Colombier return readptr;
18827dd7cddfSDavid du Colombier }
18837dd7cddfSDavid du Colombier
18847dd7cddfSDavid du Colombier if(dst->chan==CMAP8 && (src->chan==GREY1||src->chan==GREY2||src->chan==GREY4)){
18857dd7cddfSDavid du Colombier /* cheat because we know the replicated value is exactly the color map entry. */
18868ccd4a63SDavid du Colombier //if(drawdebug) iprint("Readnbit...");
18877dd7cddfSDavid du Colombier return readnbit;
18887dd7cddfSDavid du Colombier }
18897dd7cddfSDavid du Colombier
18907dd7cddfSDavid du Colombier spar->convreadcall = readfn(src);
18917dd7cddfSDavid du Colombier spar->convwritecall = writefn(dst);
18927dd7cddfSDavid du Colombier spar->convdpar = dpar;
18937dd7cddfSDavid du Colombier
18947dd7cddfSDavid du Colombier /* allocate a conversion buffer */
18957dd7cddfSDavid du Colombier spar->convbufoff = ndrawbuf;
18967dd7cddfSDavid du Colombier ndrawbuf += spar->dx*4;
18977dd7cddfSDavid du Colombier
18987dd7cddfSDavid du Colombier if(spar->dx > Dx(spar->img->r)){
18997dd7cddfSDavid du Colombier spar->convdx = spar->dx;
19007dd7cddfSDavid du Colombier spar->dx = Dx(spar->img->r);
19017dd7cddfSDavid du Colombier }
19027dd7cddfSDavid du Colombier
19038ccd4a63SDavid du Colombier //if(drawdebug) iprint("genconv...");
19047dd7cddfSDavid du Colombier return genconv;
19057dd7cddfSDavid du Colombier }
19067dd7cddfSDavid du Colombier
19077dd7cddfSDavid du Colombier ulong
_pixelbits(Memimage * i,Point pt)19087dd7cddfSDavid du Colombier _pixelbits(Memimage *i, Point pt)
19097dd7cddfSDavid du Colombier {
19107dd7cddfSDavid du Colombier uchar *p;
19117dd7cddfSDavid du Colombier ulong val;
19127dd7cddfSDavid du Colombier int off, bpp, npack;
19137dd7cddfSDavid du Colombier
19147dd7cddfSDavid du Colombier val = 0;
19157dd7cddfSDavid du Colombier p = byteaddr(i, pt);
19167dd7cddfSDavid du Colombier switch(bpp=i->depth){
19177dd7cddfSDavid du Colombier case 1:
19187dd7cddfSDavid du Colombier case 2:
19197dd7cddfSDavid du Colombier case 4:
19207dd7cddfSDavid du Colombier npack = 8/bpp;
19217dd7cddfSDavid du Colombier off = pt.x%npack;
19227dd7cddfSDavid du Colombier val = p[0] >> bpp*(npack-1-off);
19237dd7cddfSDavid du Colombier val &= (1<<bpp)-1;
19247dd7cddfSDavid du Colombier break;
19257dd7cddfSDavid du Colombier case 8:
19267dd7cddfSDavid du Colombier val = p[0];
19277dd7cddfSDavid du Colombier break;
19287dd7cddfSDavid du Colombier case 16:
19297dd7cddfSDavid du Colombier val = p[0]|(p[1]<<8);
19307dd7cddfSDavid du Colombier break;
19317dd7cddfSDavid du Colombier case 24:
19327dd7cddfSDavid du Colombier val = p[0]|(p[1]<<8)|(p[2]<<16);
19337dd7cddfSDavid du Colombier break;
19347dd7cddfSDavid du Colombier case 32:
19357dd7cddfSDavid du Colombier val = p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
19367dd7cddfSDavid du Colombier break;
19377dd7cddfSDavid du Colombier }
19387dd7cddfSDavid du Colombier while(bpp<32){
19397dd7cddfSDavid du Colombier val |= val<<bpp;
19407dd7cddfSDavid du Colombier bpp *= 2;
19417dd7cddfSDavid du Colombier }
19427dd7cddfSDavid du Colombier return val;
19437dd7cddfSDavid du Colombier }
19447dd7cddfSDavid du Colombier
19457dd7cddfSDavid du Colombier static Calcfn*
boolcopyfn(Memimage * img,Memimage * mask)19467dd7cddfSDavid du Colombier boolcopyfn(Memimage *img, Memimage *mask)
19477dd7cddfSDavid du Colombier {
19488ccd4a63SDavid du Colombier if(mask->flags&Frepl && Dx(mask->r)==1 && Dy(mask->r)==1 && pixelbits(mask, mask->r.min)==~0)
19497dd7cddfSDavid du Colombier return boolmemmove;
19507dd7cddfSDavid du Colombier
19517dd7cddfSDavid du Colombier switch(img->depth){
19527dd7cddfSDavid du Colombier case 8:
19537dd7cddfSDavid du Colombier return boolcopy8;
19547dd7cddfSDavid du Colombier case 16:
19557dd7cddfSDavid du Colombier return boolcopy16;
19567dd7cddfSDavid du Colombier case 24:
19577dd7cddfSDavid du Colombier return boolcopy24;
19587dd7cddfSDavid du Colombier case 32:
19597dd7cddfSDavid du Colombier return boolcopy32;
19607dd7cddfSDavid du Colombier default:
19617dd7cddfSDavid du Colombier assert(0 /* boolcopyfn */);
19627dd7cddfSDavid du Colombier }
1963*58da3067SDavid du Colombier return nil;
19647dd7cddfSDavid du Colombier }
19657dd7cddfSDavid du Colombier
19667dd7cddfSDavid du Colombier /*
19677dd7cddfSDavid du Colombier * Optimized draw for filling and scrolling; uses memset and memmove.
19688ccd4a63SDavid du Colombier *
19697dd7cddfSDavid du Colombier static void
19707dd7cddfSDavid du Colombier memsetb(void *vp, uchar val, int n)
19717dd7cddfSDavid du Colombier {
19727dd7cddfSDavid du Colombier uchar *p, *ep;
19737dd7cddfSDavid du Colombier
19747dd7cddfSDavid du Colombier p = vp;
19757dd7cddfSDavid du Colombier ep = p+n;
19767dd7cddfSDavid du Colombier while(p<ep)
19777dd7cddfSDavid du Colombier *p++ = val;
19787dd7cddfSDavid du Colombier }
19798ccd4a63SDavid du Colombier */
19807dd7cddfSDavid du Colombier
19817dd7cddfSDavid du Colombier static void
memsets(void * vp,ushort val,int n)19827dd7cddfSDavid du Colombier memsets(void *vp, ushort val, int n)
19837dd7cddfSDavid du Colombier {
19847dd7cddfSDavid du Colombier ushort *p, *ep;
19857dd7cddfSDavid du Colombier
19867dd7cddfSDavid du Colombier p = vp;
19877dd7cddfSDavid du Colombier ep = p+n;
19887dd7cddfSDavid du Colombier while(p<ep)
19897dd7cddfSDavid du Colombier *p++ = val;
19907dd7cddfSDavid du Colombier }
19917dd7cddfSDavid du Colombier
19927dd7cddfSDavid du Colombier static void
memsetl(void * vp,ulong val,int n)19937dd7cddfSDavid du Colombier memsetl(void *vp, ulong val, int n)
19947dd7cddfSDavid du Colombier {
19957dd7cddfSDavid du Colombier ulong *p, *ep;
19967dd7cddfSDavid du Colombier
19977dd7cddfSDavid du Colombier p = vp;
19987dd7cddfSDavid du Colombier ep = p+n;
19997dd7cddfSDavid du Colombier while(p<ep)
20007dd7cddfSDavid du Colombier *p++ = val;
20017dd7cddfSDavid du Colombier }
20027dd7cddfSDavid du Colombier
20038ccd4a63SDavid du Colombier static void
memset24(void * vp,ulong val,int n)20047dd7cddfSDavid du Colombier memset24(void *vp, ulong val, int n)
20057dd7cddfSDavid du Colombier {
20067dd7cddfSDavid du Colombier uchar *p, *ep;
20077dd7cddfSDavid du Colombier uchar a,b,c;
20087dd7cddfSDavid du Colombier
20097dd7cddfSDavid du Colombier p = vp;
20107dd7cddfSDavid du Colombier ep = p+3*n;
20117dd7cddfSDavid du Colombier a = val;
20127dd7cddfSDavid du Colombier b = val>>8;
20137dd7cddfSDavid du Colombier c = val>>16;
20147dd7cddfSDavid du Colombier while(p<ep){
20157dd7cddfSDavid du Colombier *p++ = a;
20167dd7cddfSDavid du Colombier *p++ = b;
20177dd7cddfSDavid du Colombier *p++ = c;
20187dd7cddfSDavid du Colombier }
20197dd7cddfSDavid du Colombier }
20207dd7cddfSDavid du Colombier
20217dd7cddfSDavid du Colombier ulong
_imgtorgba(Memimage * img,ulong val)20227dd7cddfSDavid du Colombier _imgtorgba(Memimage *img, ulong val)
20237dd7cddfSDavid du Colombier {
20247dd7cddfSDavid du Colombier uchar r, g, b, a;
20257dd7cddfSDavid du Colombier int nb, ov, v;
20267dd7cddfSDavid du Colombier ulong chan;
20277dd7cddfSDavid du Colombier uchar *p;
20287dd7cddfSDavid du Colombier
20297dd7cddfSDavid du Colombier a = 0xFF;
20307dd7cddfSDavid du Colombier r = g = b = 0xAA; /* garbage */
20317dd7cddfSDavid du Colombier for(chan=img->chan; chan; chan>>=8){
20327dd7cddfSDavid du Colombier nb = NBITS(chan);
20337dd7cddfSDavid du Colombier ov = v = val&((1<<nb)-1);
20347dd7cddfSDavid du Colombier val >>= nb;
20357dd7cddfSDavid du Colombier
20367dd7cddfSDavid du Colombier while(nb < 8){
20377dd7cddfSDavid du Colombier v |= v<<nb;
20387dd7cddfSDavid du Colombier nb *= 2;
20397dd7cddfSDavid du Colombier }
20407dd7cddfSDavid du Colombier v >>= (nb-8);
20417dd7cddfSDavid du Colombier
20427dd7cddfSDavid du Colombier switch(TYPE(chan)){
20437dd7cddfSDavid du Colombier case CRed:
20447dd7cddfSDavid du Colombier r = v;
20457dd7cddfSDavid du Colombier break;
20467dd7cddfSDavid du Colombier case CGreen:
20477dd7cddfSDavid du Colombier g = v;
20487dd7cddfSDavid du Colombier break;
20497dd7cddfSDavid du Colombier case CBlue:
20507dd7cddfSDavid du Colombier b = v;
20517dd7cddfSDavid du Colombier break;
20527dd7cddfSDavid du Colombier case CAlpha:
20537dd7cddfSDavid du Colombier a = v;
20547dd7cddfSDavid du Colombier break;
20557dd7cddfSDavid du Colombier case CGrey:
20567dd7cddfSDavid du Colombier r = g = b = v;
20577dd7cddfSDavid du Colombier break;
20587dd7cddfSDavid du Colombier case CMap:
20597dd7cddfSDavid du Colombier p = img->cmap->cmap2rgb+3*ov;
20607dd7cddfSDavid du Colombier r = *p++;
20617dd7cddfSDavid du Colombier g = *p++;
20627dd7cddfSDavid du Colombier b = *p;
20637dd7cddfSDavid du Colombier break;
20647dd7cddfSDavid du Colombier }
20657dd7cddfSDavid du Colombier }
20667dd7cddfSDavid du Colombier return (r<<24)|(g<<16)|(b<<8)|a;
20677dd7cddfSDavid du Colombier }
20687dd7cddfSDavid du Colombier
20697dd7cddfSDavid du Colombier ulong
_rgbatoimg(Memimage * img,ulong rgba)20707dd7cddfSDavid du Colombier _rgbatoimg(Memimage *img, ulong rgba)
20717dd7cddfSDavid du Colombier {
20727dd7cddfSDavid du Colombier ulong chan;
20737dd7cddfSDavid du Colombier int d, nb;
20747dd7cddfSDavid du Colombier ulong v;
20757dd7cddfSDavid du Colombier uchar *p, r, g, b, a, m;
20767dd7cddfSDavid du Colombier
20777dd7cddfSDavid du Colombier v = 0;
20787dd7cddfSDavid du Colombier r = rgba>>24;
20797dd7cddfSDavid du Colombier g = rgba>>16;
20807dd7cddfSDavid du Colombier b = rgba>>8;
20817dd7cddfSDavid du Colombier a = rgba;
20827dd7cddfSDavid du Colombier d = 0;
20837dd7cddfSDavid du Colombier for(chan=img->chan; chan; chan>>=8){
20847dd7cddfSDavid du Colombier nb = NBITS(chan);
20857dd7cddfSDavid du Colombier switch(TYPE(chan)){
20867dd7cddfSDavid du Colombier case CRed:
20877dd7cddfSDavid du Colombier v |= (r>>(8-nb))<<d;
20887dd7cddfSDavid du Colombier break;
20897dd7cddfSDavid du Colombier case CGreen:
20907dd7cddfSDavid du Colombier v |= (g>>(8-nb))<<d;
20917dd7cddfSDavid du Colombier break;
20927dd7cddfSDavid du Colombier case CBlue:
20937dd7cddfSDavid du Colombier v |= (b>>(8-nb))<<d;
20947dd7cddfSDavid du Colombier break;
20957dd7cddfSDavid du Colombier case CAlpha:
20967dd7cddfSDavid du Colombier v |= (a>>(8-nb))<<d;
20977dd7cddfSDavid du Colombier break;
20987dd7cddfSDavid du Colombier case CMap:
20997dd7cddfSDavid du Colombier p = img->cmap->rgb2cmap;
21007dd7cddfSDavid du Colombier m = p[(r>>4)*256+(g>>4)*16+(b>>4)];
210159cc4ca5SDavid du Colombier v |= (m>>(8-nb))<<d;
21027dd7cddfSDavid du Colombier break;
21037dd7cddfSDavid du Colombier case CGrey:
21047dd7cddfSDavid du Colombier m = RGB2K(r,g,b);
210559cc4ca5SDavid du Colombier v |= (m>>(8-nb))<<d;
21067dd7cddfSDavid du Colombier break;
21077dd7cddfSDavid du Colombier }
21087dd7cddfSDavid du Colombier d += nb;
21097dd7cddfSDavid du Colombier }
21108ccd4a63SDavid du Colombier // print("rgba2img %.8lux = %.*lux\n", rgba, 2*d/8, v);
21117dd7cddfSDavid du Colombier return v;
21127dd7cddfSDavid du Colombier }
21137dd7cddfSDavid du Colombier
21148ccd4a63SDavid du Colombier #define DBG if(0)
21157dd7cddfSDavid du Colombier static int
memoptdraw(Memdrawparam * par)21167dd7cddfSDavid du Colombier memoptdraw(Memdrawparam *par)
21177dd7cddfSDavid du Colombier {
21188ccd4a63SDavid du Colombier int m, y, dy, dx, op;
21197dd7cddfSDavid du Colombier ulong v;
21207dd7cddfSDavid du Colombier Memimage *src;
21217dd7cddfSDavid du Colombier Memimage *dst;
21227dd7cddfSDavid du Colombier
21237dd7cddfSDavid du Colombier dx = Dx(par->r);
21247dd7cddfSDavid du Colombier dy = Dy(par->r);
21257dd7cddfSDavid du Colombier src = par->src;
21267dd7cddfSDavid du Colombier dst = par->dst;
21278ccd4a63SDavid du Colombier op = par->op;
21287dd7cddfSDavid du Colombier
21298ccd4a63SDavid du Colombier DBG print("state %lux mval %lux dd %d\n", par->state, par->mval, dst->depth);
21307dd7cddfSDavid du Colombier /*
21317dd7cddfSDavid du Colombier * If we have an opaque mask and source is one opaque pixel we can convert to the
21327dd7cddfSDavid du Colombier * destination format and just replicate with memset.
21337dd7cddfSDavid du Colombier */
21347dd7cddfSDavid du Colombier m = Simplesrc|Simplemask|Fullmask;
21358ccd4a63SDavid du Colombier if((par->state&m)==m && (par->srgba&0xFF) == 0xFF && (op ==S || op == SoverD)){
21367dd7cddfSDavid du Colombier uchar *dp, p[4];
213759cc4ca5SDavid du Colombier int d, dwid, ppb, np, nb;
21387dd7cddfSDavid du Colombier uchar lm, rm;
21397dd7cddfSDavid du Colombier
21408ccd4a63SDavid du Colombier DBG print("memopt, dst %p, dst->data->bdata %p\n", dst, dst->data->bdata);
21417dd7cddfSDavid du Colombier dwid = dst->width*sizeof(ulong);
21427dd7cddfSDavid du Colombier dp = byteaddr(dst, par->r.min);
21437dd7cddfSDavid du Colombier v = par->sdval;
21448ccd4a63SDavid du Colombier DBG print("sdval %lud, depth %d\n", v, dst->depth);
21457dd7cddfSDavid du Colombier switch(dst->depth){
21467dd7cddfSDavid du Colombier case 1:
21477dd7cddfSDavid du Colombier case 2:
21487dd7cddfSDavid du Colombier case 4:
214959cc4ca5SDavid du Colombier for(d=dst->depth; d<8; d*=2)
215059cc4ca5SDavid du Colombier v |= (v<<d);
21517dd7cddfSDavid du Colombier ppb = 8/dst->depth; /* pixels per byte */
21527dd7cddfSDavid du Colombier m = ppb-1;
21537dd7cddfSDavid du Colombier /* left edge */
21547dd7cddfSDavid du Colombier np = par->r.min.x&m; /* no. pixels unused on left side of word */
21557dd7cddfSDavid du Colombier dx -= (ppb-np);
21567dd7cddfSDavid du Colombier nb = 8 - np * dst->depth; /* no. bits used on right side of word */
21577dd7cddfSDavid du Colombier lm = (1<<nb)-1;
21588ccd4a63SDavid 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);
21597dd7cddfSDavid du Colombier
21607dd7cddfSDavid du Colombier /* right edge */
21617dd7cddfSDavid du Colombier np = par->r.max.x&m; /* no. pixels used on left side of word */
21627dd7cddfSDavid du Colombier dx -= np;
21637dd7cddfSDavid du Colombier nb = 8 - np * dst->depth; /* no. bits unused on right side of word */
21647dd7cddfSDavid du Colombier rm = ~((1<<nb)-1);
21658ccd4a63SDavid 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);
21667dd7cddfSDavid du Colombier
21678ccd4a63SDavid du Colombier DBG print("dx %d Dx %d\n", dx, Dx(par->r));
21687dd7cddfSDavid du Colombier /* lm, rm are masks that are 1 where we should touch the bits */
21697dd7cddfSDavid du Colombier if(dx < 0){ /* just one byte */
21707dd7cddfSDavid du Colombier lm &= rm;
21717dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid)
21727dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & lm;
21737dd7cddfSDavid du Colombier }else if(dx == 0){ /* no full bytes */
21747dd7cddfSDavid du Colombier if(lm)
21757dd7cddfSDavid du Colombier dwid--;
21767dd7cddfSDavid du Colombier
21777dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid){
21787dd7cddfSDavid du Colombier if(lm){
21798ccd4a63SDavid du Colombier DBG print("dp %p v %lux lm %ux (v ^ *dp) & lm %lux\n", dp, v, lm, (v^*dp)&lm);
21807dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & lm;
21817dd7cddfSDavid du Colombier dp++;
21827dd7cddfSDavid du Colombier }
21837dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & rm;
21847dd7cddfSDavid du Colombier }
21857dd7cddfSDavid du Colombier }else{ /* full bytes in middle */
21867dd7cddfSDavid du Colombier dx /= ppb;
21877dd7cddfSDavid du Colombier if(lm)
21887dd7cddfSDavid du Colombier dwid--;
21897dd7cddfSDavid du Colombier dwid -= dx;
21907dd7cddfSDavid du Colombier
21917dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid){
21927dd7cddfSDavid du Colombier if(lm){
21937dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & lm;
21947dd7cddfSDavid du Colombier dp++;
21957dd7cddfSDavid du Colombier }
21967dd7cddfSDavid du Colombier memset(dp, v, dx);
21977dd7cddfSDavid du Colombier dp += dx;
21987dd7cddfSDavid du Colombier *dp ^= (v ^ *dp) & rm;
21997dd7cddfSDavid du Colombier }
22007dd7cddfSDavid du Colombier }
22017dd7cddfSDavid du Colombier return 1;
22027dd7cddfSDavid du Colombier case 8:
22037dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid)
22047dd7cddfSDavid du Colombier memset(dp, v, dx);
22057dd7cddfSDavid du Colombier return 1;
22067dd7cddfSDavid du Colombier case 16:
22077dd7cddfSDavid du Colombier p[0] = v; /* make little endian */
22087dd7cddfSDavid du Colombier p[1] = v>>8;
22097dd7cddfSDavid du Colombier v = *(ushort*)p;
22108ccd4a63SDavid du Colombier DBG print("dp=%p; dx=%d; for(y=0; y<%d; y++, dp+=%d)\nmemsets(dp, v, dx);\n",
22118ccd4a63SDavid du Colombier dp, dx, dy, dwid);
22127dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid)
22137dd7cddfSDavid du Colombier memsets(dp, v, dx);
22147dd7cddfSDavid du Colombier return 1;
22157dd7cddfSDavid du Colombier case 24:
22167dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid)
22177dd7cddfSDavid du Colombier memset24(dp, v, dx);
22187dd7cddfSDavid du Colombier return 1;
22197dd7cddfSDavid du Colombier case 32:
22207dd7cddfSDavid du Colombier p[0] = v; /* make little endian */
22217dd7cddfSDavid du Colombier p[1] = v>>8;
22227dd7cddfSDavid du Colombier p[2] = v>>16;
22237dd7cddfSDavid du Colombier p[3] = v>>24;
22247dd7cddfSDavid du Colombier v = *(ulong*)p;
22257dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid)
22267dd7cddfSDavid du Colombier memsetl(dp, v, dx);
22277dd7cddfSDavid du Colombier return 1;
22287dd7cddfSDavid du Colombier default:
22297dd7cddfSDavid du Colombier assert(0 /* bad dest depth in memoptdraw */);
22307dd7cddfSDavid du Colombier }
22317dd7cddfSDavid du Colombier }
22327dd7cddfSDavid du Colombier
22337dd7cddfSDavid du Colombier /*
22347dd7cddfSDavid du Colombier * If no source alpha, an opaque mask, we can just copy the
22357dd7cddfSDavid du Colombier * source onto the destination. If the channels are the same and
22367dd7cddfSDavid du Colombier * the source is not replicated, memmove suffices.
22377dd7cddfSDavid du Colombier */
22387dd7cddfSDavid du Colombier m = Simplemask|Fullmask;
22397dd7cddfSDavid du Colombier if((par->state&(m|Replsrc))==m && src->depth >= 8
22408ccd4a63SDavid du Colombier && src->chan == dst->chan && !(src->flags&Falpha) && (op == S || op == SoverD)){
22417dd7cddfSDavid du Colombier uchar *sp, *dp;
22427dd7cddfSDavid du Colombier long swid, dwid, nb;
22437dd7cddfSDavid du Colombier int dir;
22447dd7cddfSDavid du Colombier
22457dd7cddfSDavid du Colombier if(src->data == dst->data && byteaddr(dst, par->r.min) > byteaddr(src, par->sr.min))
22467dd7cddfSDavid du Colombier dir = -1;
22477dd7cddfSDavid du Colombier else
22487dd7cddfSDavid du Colombier dir = 1;
22497dd7cddfSDavid du Colombier
22507dd7cddfSDavid du Colombier swid = src->width*sizeof(ulong);
22517dd7cddfSDavid du Colombier dwid = dst->width*sizeof(ulong);
22527dd7cddfSDavid du Colombier sp = byteaddr(src, par->sr.min);
22537dd7cddfSDavid du Colombier dp = byteaddr(dst, par->r.min);
22547dd7cddfSDavid du Colombier if(dir == -1){
22557dd7cddfSDavid du Colombier sp += (dy-1)*swid;
22567dd7cddfSDavid du Colombier dp += (dy-1)*dwid;
22577dd7cddfSDavid du Colombier swid = -swid;
22587dd7cddfSDavid du Colombier dwid = -dwid;
22597dd7cddfSDavid du Colombier }
22607dd7cddfSDavid du Colombier nb = (dx*src->depth)/8;
22617dd7cddfSDavid du Colombier for(y=0; y<dy; y++, sp+=swid, dp+=dwid)
22627dd7cddfSDavid du Colombier memmove(dp, sp, nb);
22637dd7cddfSDavid du Colombier return 1;
22647dd7cddfSDavid du Colombier }
22657dd7cddfSDavid du Colombier
22667dd7cddfSDavid du Colombier /*
22677dd7cddfSDavid du Colombier * If we have a 1-bit mask, 1-bit source, and 1-bit destination, and
22687dd7cddfSDavid du Colombier * they're all bit aligned, we can just use bit operators. This happens
22697dd7cddfSDavid du Colombier * when we're manipulating boolean masks, e.g. in the arc code.
22707dd7cddfSDavid du Colombier */
22717dd7cddfSDavid du Colombier if((par->state&(Simplemask|Simplesrc|Replmask|Replsrc))==0
22727dd7cddfSDavid du Colombier && dst->chan==GREY1 && src->chan==GREY1 && par->mask->chan==GREY1
22737dd7cddfSDavid du Colombier && (par->r.min.x&7)==(par->sr.min.x&7) && (par->r.min.x&7)==(par->mr.min.x&7)){
22747dd7cddfSDavid du Colombier uchar *sp, *dp, *mp;
22757dd7cddfSDavid du Colombier uchar lm, rm;
22767dd7cddfSDavid du Colombier long swid, dwid, mwid;
22777dd7cddfSDavid du Colombier int i, x, dir;
22787dd7cddfSDavid du Colombier
22797dd7cddfSDavid du Colombier sp = byteaddr(src, par->sr.min);
22807dd7cddfSDavid du Colombier dp = byteaddr(dst, par->r.min);
22817dd7cddfSDavid du Colombier mp = byteaddr(par->mask, par->mr.min);
22827dd7cddfSDavid du Colombier swid = src->width*sizeof(ulong);
22837dd7cddfSDavid du Colombier dwid = dst->width*sizeof(ulong);
22847dd7cddfSDavid du Colombier mwid = par->mask->width*sizeof(ulong);
22857dd7cddfSDavid du Colombier
22867dd7cddfSDavid du Colombier if(src->data == dst->data && byteaddr(dst, par->r.min) > byteaddr(src, par->sr.min)){
22877dd7cddfSDavid du Colombier dir = -1;
22887dd7cddfSDavid du Colombier }else
22897dd7cddfSDavid du Colombier dir = 1;
22907dd7cddfSDavid du Colombier
22917dd7cddfSDavid du Colombier lm = 0xFF>>(par->r.min.x&7);
22927dd7cddfSDavid du Colombier rm = 0xFF<<(8-(par->r.max.x&7));
22937dd7cddfSDavid du Colombier dx -= (8-(par->r.min.x&7)) + (par->r.max.x&7);
22947dd7cddfSDavid du Colombier
22957dd7cddfSDavid du Colombier if(dx < 0){ /* one byte wide */
22967dd7cddfSDavid du Colombier lm &= rm;
22977dd7cddfSDavid du Colombier if(dir == -1){
22987dd7cddfSDavid du Colombier dp += dwid*(dy-1);
22997dd7cddfSDavid du Colombier sp += swid*(dy-1);
23007dd7cddfSDavid du Colombier mp += mwid*(dy-1);
23017dd7cddfSDavid du Colombier dwid = -dwid;
23027dd7cddfSDavid du Colombier swid = -swid;
23037dd7cddfSDavid du Colombier mwid = -mwid;
23047dd7cddfSDavid du Colombier }
23057dd7cddfSDavid du Colombier for(y=0; y<dy; y++){
23067dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp) & *mp & lm;
23077dd7cddfSDavid du Colombier dp += dwid;
23087dd7cddfSDavid du Colombier sp += swid;
23097dd7cddfSDavid du Colombier mp += mwid;
23107dd7cddfSDavid du Colombier }
23117dd7cddfSDavid du Colombier return 1;
23127dd7cddfSDavid du Colombier }
23137dd7cddfSDavid du Colombier
23147dd7cddfSDavid du Colombier dx /= 8;
23157dd7cddfSDavid du Colombier if(dir == 1){
23167dd7cddfSDavid du Colombier i = (lm!=0)+dx+(rm!=0);
23177dd7cddfSDavid du Colombier mwid -= i;
23187dd7cddfSDavid du Colombier swid -= i;
23197dd7cddfSDavid du Colombier dwid -= i;
23207dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid, sp+=swid, mp+=mwid){
23217dd7cddfSDavid du Colombier if(lm){
23227dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp++) & *mp++ & lm;
23237dd7cddfSDavid du Colombier dp++;
23247dd7cddfSDavid du Colombier }
23257dd7cddfSDavid du Colombier for(x=0; x<dx; x++){
23267dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp++) & *mp++;
23277dd7cddfSDavid du Colombier dp++;
23287dd7cddfSDavid du Colombier }
23297dd7cddfSDavid du Colombier if(rm){
23307dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp++) & *mp++ & rm;
23317dd7cddfSDavid du Colombier dp++;
23327dd7cddfSDavid du Colombier }
23337dd7cddfSDavid du Colombier }
23347dd7cddfSDavid du Colombier return 1;
23357dd7cddfSDavid du Colombier }else{
23367dd7cddfSDavid du Colombier /* dir == -1 */
23377dd7cddfSDavid du Colombier i = (lm!=0)+dx+(rm!=0);
23387dd7cddfSDavid du Colombier dp += dwid*(dy-1)+i-1;
23397dd7cddfSDavid du Colombier sp += swid*(dy-1)+i-1;
23407dd7cddfSDavid du Colombier mp += mwid*(dy-1)+i-1;
23417dd7cddfSDavid du Colombier dwid = -dwid+i;
23427dd7cddfSDavid du Colombier swid = -swid+i;
23437dd7cddfSDavid du Colombier mwid = -mwid+i;
23447dd7cddfSDavid du Colombier for(y=0; y<dy; y++, dp+=dwid, sp+=swid, mp+=mwid){
23457dd7cddfSDavid du Colombier if(rm){
23467dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp--) & *mp-- & rm;
23477dd7cddfSDavid du Colombier dp--;
23487dd7cddfSDavid du Colombier }
23497dd7cddfSDavid du Colombier for(x=0; x<dx; x++){
23507dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp--) & *mp--;
23517dd7cddfSDavid du Colombier dp--;
23527dd7cddfSDavid du Colombier }
23537dd7cddfSDavid du Colombier if(lm){
23547dd7cddfSDavid du Colombier *dp ^= (*dp ^ *sp--) & *mp-- & lm;
23557dd7cddfSDavid du Colombier dp--;
23567dd7cddfSDavid du Colombier }
23577dd7cddfSDavid du Colombier }
23587dd7cddfSDavid du Colombier }
23597dd7cddfSDavid du Colombier return 1;
23607dd7cddfSDavid du Colombier }
23617dd7cddfSDavid du Colombier return 0;
23627dd7cddfSDavid du Colombier }
23638ccd4a63SDavid du Colombier #undef DBG
23647dd7cddfSDavid du Colombier
23657dd7cddfSDavid du Colombier /*
23667dd7cddfSDavid du Colombier * Boolean character drawing.
23677dd7cddfSDavid du Colombier * Solid opaque color through a 1-bit greyscale mask.
23687dd7cddfSDavid du Colombier */
23697dd7cddfSDavid du Colombier #define DBG if(0)
23707dd7cddfSDavid du Colombier static int
chardraw(Memdrawparam * par)23717dd7cddfSDavid du Colombier chardraw(Memdrawparam *par)
23727dd7cddfSDavid du Colombier {
23737dd7cddfSDavid du Colombier ulong bits;
23748ccd4a63SDavid du Colombier int i, ddepth, dy, dx, x, bx, ex, y, npack, bsh, depth, op;
23757dd7cddfSDavid du Colombier ulong v, maskwid, dstwid;
23767dd7cddfSDavid du Colombier uchar *wp, *rp, *q, *wc;
23777dd7cddfSDavid du Colombier ushort *ws;
23787dd7cddfSDavid du Colombier ulong *wl;
23797dd7cddfSDavid du Colombier uchar sp[4];
23807dd7cddfSDavid du Colombier Rectangle r, mr;
23817dd7cddfSDavid du Colombier Memimage *mask, *src, *dst;
23827dd7cddfSDavid du Colombier
23837dd7cddfSDavid 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",
23847dd7cddfSDavid du Colombier par->mask->flags, par->mask->depth, par->src->flags,
23857dd7cddfSDavid du Colombier Dx(par->src->r), Dy(par->src->r), par->dst->depth, par->dst->data, par->src->data);
23867dd7cddfSDavid du Colombier
23877dd7cddfSDavid du Colombier mask = par->mask;
23887dd7cddfSDavid du Colombier src = par->src;
23897dd7cddfSDavid du Colombier dst = par->dst;
23907dd7cddfSDavid du Colombier r = par->r;
23917dd7cddfSDavid du Colombier mr = par->mr;
23928ccd4a63SDavid du Colombier op = par->op;
23937dd7cddfSDavid du Colombier
23947dd7cddfSDavid du Colombier if((par->state&(Replsrc|Simplesrc|Replmask)) != (Replsrc|Simplesrc)
23958ccd4a63SDavid du Colombier || mask->depth != 1 || src->flags&Falpha || dst->depth<8 || dst->data==src->data
23968ccd4a63SDavid du Colombier || op != SoverD)
23977dd7cddfSDavid du Colombier return 0;
23987dd7cddfSDavid du Colombier
23998ccd4a63SDavid du Colombier //if(drawdebug) iprint("chardraw...");
24008ccd4a63SDavid du Colombier
24017dd7cddfSDavid du Colombier depth = mask->depth;
24027dd7cddfSDavid du Colombier maskwid = mask->width*sizeof(ulong);
24037dd7cddfSDavid du Colombier rp = byteaddr(mask, mr.min);
24047dd7cddfSDavid du Colombier npack = 8/depth;
24057dd7cddfSDavid du Colombier bsh = (mr.min.x % npack) * depth;
24067dd7cddfSDavid du Colombier
24077dd7cddfSDavid du Colombier wp = byteaddr(dst, r.min);
24087dd7cddfSDavid du Colombier dstwid = dst->width*sizeof(ulong);
24097dd7cddfSDavid du Colombier DBG print("bsh %d\n", bsh);
24107dd7cddfSDavid du Colombier dy = Dy(r);
24117dd7cddfSDavid du Colombier dx = Dx(r);
24127dd7cddfSDavid du Colombier
24137dd7cddfSDavid du Colombier ddepth = dst->depth;
24147dd7cddfSDavid du Colombier
24157dd7cddfSDavid du Colombier /*
24167dd7cddfSDavid du Colombier * for loop counts from bsh to bsh+dx
24177dd7cddfSDavid du Colombier *
24187dd7cddfSDavid du Colombier * we want the bottom bits to be the amount
24197dd7cddfSDavid du Colombier * to shift the pixels down, so for n≡0 (mod 8) we want
24207dd7cddfSDavid du Colombier * bottom bits 7. for n≡1, 6, etc.
24217dd7cddfSDavid du Colombier * the bits come from -n-1.
24227dd7cddfSDavid du Colombier */
24237dd7cddfSDavid du Colombier
24247dd7cddfSDavid du Colombier bx = -bsh-1;
24257dd7cddfSDavid du Colombier ex = -bsh-1-dx;
2426*58da3067SDavid du Colombier SET(bits);
24277dd7cddfSDavid du Colombier v = par->sdval;
24287dd7cddfSDavid du Colombier
24297dd7cddfSDavid du Colombier /* make little endian */
24307dd7cddfSDavid du Colombier sp[0] = v;
24317dd7cddfSDavid du Colombier sp[1] = v>>8;
24327dd7cddfSDavid du Colombier sp[2] = v>>16;
24337dd7cddfSDavid du Colombier sp[3] = v>>24;
24347dd7cddfSDavid du Colombier
24358ccd4a63SDavid du Colombier //print("sp %x %x %x %x\n", sp[0], sp[1], sp[2], sp[3]);
24367dd7cddfSDavid du Colombier for(y=0; y<dy; y++, rp+=maskwid, wp+=dstwid){
24377dd7cddfSDavid du Colombier q = rp;
24387dd7cddfSDavid du Colombier if(bsh)
24397dd7cddfSDavid du Colombier bits = *q++;
24407dd7cddfSDavid du Colombier switch(ddepth){
24417dd7cddfSDavid du Colombier case 8:
24428ccd4a63SDavid du Colombier //if(drawdebug) iprint("8loop...");
24437dd7cddfSDavid du Colombier wc = wp;
24447dd7cddfSDavid du Colombier for(x=bx; x>ex; x--, wc++){
24457dd7cddfSDavid du Colombier i = x&7;
24467dd7cddfSDavid du Colombier if(i == 8-1)
24477dd7cddfSDavid du Colombier bits = *q++;
24487dd7cddfSDavid du Colombier DBG print("bits %lux sh %d...", bits, i);
24497dd7cddfSDavid du Colombier if((bits>>i)&1)
24507dd7cddfSDavid du Colombier *wc = v;
24517dd7cddfSDavid du Colombier }
24527dd7cddfSDavid du Colombier break;
24537dd7cddfSDavid du Colombier case 16:
24547dd7cddfSDavid du Colombier ws = (ushort*)wp;
24557dd7cddfSDavid du Colombier v = *(ushort*)sp;
24567dd7cddfSDavid du Colombier for(x=bx; x>ex; x--, ws++){
24577dd7cddfSDavid du Colombier i = x&7;
24587dd7cddfSDavid du Colombier if(i == 8-1)
24597dd7cddfSDavid du Colombier bits = *q++;
24607dd7cddfSDavid du Colombier DBG print("bits %lux sh %d...", bits, i);
24617dd7cddfSDavid du Colombier if((bits>>i)&1)
24627dd7cddfSDavid du Colombier *ws = v;
24637dd7cddfSDavid du Colombier }
24647dd7cddfSDavid du Colombier break;
24657dd7cddfSDavid du Colombier case 24:
24667dd7cddfSDavid du Colombier wc = wp;
24677dd7cddfSDavid du Colombier for(x=bx; x>ex; x--, wc+=3){
24687dd7cddfSDavid du Colombier i = x&7;
24697dd7cddfSDavid du Colombier if(i == 8-1)
24707dd7cddfSDavid du Colombier bits = *q++;
24717dd7cddfSDavid du Colombier DBG print("bits %lux sh %d...", bits, i);
24727dd7cddfSDavid du Colombier if((bits>>i)&1){
24737dd7cddfSDavid du Colombier wc[0] = sp[0];
24747dd7cddfSDavid du Colombier wc[1] = sp[1];
24757dd7cddfSDavid du Colombier wc[2] = sp[2];
24767dd7cddfSDavid du Colombier }
24777dd7cddfSDavid du Colombier }
24787dd7cddfSDavid du Colombier break;
24797dd7cddfSDavid du Colombier case 32:
24807dd7cddfSDavid du Colombier wl = (ulong*)wp;
24817dd7cddfSDavid du Colombier v = *(ulong*)sp;
24827dd7cddfSDavid du Colombier for(x=bx; x>ex; x--, wl++){
24837dd7cddfSDavid du Colombier i = x&7;
24847dd7cddfSDavid du Colombier if(i == 8-1)
24857dd7cddfSDavid du Colombier bits = *q++;
24867dd7cddfSDavid du Colombier DBG iprint("bits %lux sh %d...", bits, i);
24877dd7cddfSDavid du Colombier if((bits>>i)&1)
24887dd7cddfSDavid du Colombier *wl = v;
24897dd7cddfSDavid du Colombier }
24907dd7cddfSDavid du Colombier break;
24917dd7cddfSDavid du Colombier }
24927dd7cddfSDavid du Colombier }
24937dd7cddfSDavid du Colombier
24947dd7cddfSDavid du Colombier DBG print("\n");
24957dd7cddfSDavid du Colombier return 1;
24967dd7cddfSDavid du Colombier }
24977dd7cddfSDavid du Colombier #undef DBG
24987dd7cddfSDavid du Colombier
24998ccd4a63SDavid du Colombier
25008ccd4a63SDavid du Colombier /*
25018ccd4a63SDavid du Colombier * Fill entire byte with replicated (if necessary) copy of source pixel,
25028ccd4a63SDavid du Colombier * assuming destination ldepth is >= source ldepth.
25038ccd4a63SDavid du Colombier *
25048ccd4a63SDavid du Colombier * This code is just plain wrong for >8bpp.
25058ccd4a63SDavid du Colombier *
25068ccd4a63SDavid du Colombier ulong
25078ccd4a63SDavid du Colombier membyteval(Memimage *src)
25088ccd4a63SDavid du Colombier {
25098ccd4a63SDavid du Colombier int i, val, bpp;
25108ccd4a63SDavid du Colombier uchar uc;
25118ccd4a63SDavid du Colombier
25128ccd4a63SDavid du Colombier unloadmemimage(src, src->r, &uc, 1);
25138ccd4a63SDavid du Colombier bpp = src->depth;
25148ccd4a63SDavid du Colombier uc <<= (src->r.min.x&(7/src->depth))*src->depth;
25158ccd4a63SDavid du Colombier uc &= ~(0xFF>>bpp);
25168ccd4a63SDavid du Colombier // pixel value is now in high part of byte. repeat throughout byte
25178ccd4a63SDavid du Colombier val = uc;
25188ccd4a63SDavid du Colombier for(i=bpp; i<8; i<<=1)
25198ccd4a63SDavid du Colombier val |= val>>i;
25208ccd4a63SDavid du Colombier return val;
25218ccd4a63SDavid du Colombier }
25228ccd4a63SDavid du Colombier *
25238ccd4a63SDavid du Colombier */
25248ccd4a63SDavid du Colombier
252559cc4ca5SDavid du Colombier void
_memfillcolor(Memimage * i,ulong val)252659cc4ca5SDavid du Colombier _memfillcolor(Memimage *i, ulong val)
252759cc4ca5SDavid du Colombier {
252859cc4ca5SDavid du Colombier ulong bits;
252959cc4ca5SDavid du Colombier int d, y;
253059cc4ca5SDavid du Colombier
253159cc4ca5SDavid du Colombier if(val == DNofill)
253259cc4ca5SDavid du Colombier return;
253359cc4ca5SDavid du Colombier
253459cc4ca5SDavid du Colombier bits = _rgbatoimg(i, val);
253559cc4ca5SDavid du Colombier switch(i->depth){
253659cc4ca5SDavid du Colombier case 24: /* 24-bit images suck */
253759cc4ca5SDavid du Colombier for(y=i->r.min.y; y<i->r.max.y; y++)
253859cc4ca5SDavid du Colombier memset24(byteaddr(i, Pt(i->r.min.x, y)), bits, Dx(i->r));
253959cc4ca5SDavid du Colombier break;
254059cc4ca5SDavid du Colombier default: /* 1, 2, 4, 8, 16, 32 */
254159cc4ca5SDavid du Colombier for(d=i->depth; d<32; d*=2)
254259cc4ca5SDavid du Colombier bits = (bits << d) | bits;
254359cc4ca5SDavid du Colombier memsetl(wordaddr(i, i->r.min), bits, i->width*Dy(i->r));
254459cc4ca5SDavid du Colombier break;
254559cc4ca5SDavid du Colombier }
254659cc4ca5SDavid du Colombier }
25478ccd4a63SDavid du Colombier
2548