aboutsummaryrefslogtreecommitdiff
path: root/SHADE.C
blob: d4699ba63958e77e8ce04b16789e5fc29c668736 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*----------------------------------------------------------------------*/
/*  									*/
/*        shade.c --							*/
/*  									*/
/*----------------------------------------------------------------------*/

#include <system.h>
#include <prism.h>

#define local
extern BoxBM temp;
extern BOOL erasing;
extern Range *shadeRange;
extern struct TmpRas tmpRas;
extern BoxBM canvas;

void MaskRange();

/*----------------------------------------------------------------------*/
/*  SHADE mode:								*/
/*----------------------------------------------------------------------*/
void DoShade(ob,canv,clip)   BMOB *ob; BoxBM *canv; Box *clip; {		    
    Box b;  
    BOOL res;
    int lo,hi;
    if (BMPlaneSize(ob->pict.bm)> (tmpRas.Size/2)) return;
    if (SaveSizeBM(temp.bm, ob)) return;
    temp.box = ob->pict.box;
    CopyBoxBM(canv, &temp, &temp.box, clip, REPOP);
    if (erasing) { lo = shadeRange->low+1; hi = shadeRange->high; }
	else {lo = shadeRange->low; hi = shadeRange->high - 1; }
    if (shadeRange==NULL) setmem(tmpRas.RasPtr,BMPlaneSize(ob->pict.bm),0xff);
    else MaskRange(temp.bm, tmpRas.RasPtr,tmpRas.RasPtr +tmpRas.Size/2,lo,hi);
    if (clip) res = BoxAnd(&b,&ob->pict.box,clip); 
	else { res = YES; b = ob->pict.box; }
    if (res) ShadePaint(ob->pict.bm,ob->mask, b.x - ob->pict.box.x,b.y - ob->pict.box.y, 
	canv->bm, b.x - canv->box.x, b.y - canv->box.y,
	b.w, b.h, erasing? MINUSOP: PLUSOP, tmpRas.RasPtr);
    }


/*----------------------------------------------------------------------*/
/* MaskRange: Build a mask for a bitmap which has 1's for every pixel	*/
/* in [lower..upper] inclusive.						*/
/*									*/
/*	Thanks to David Maynard for suggesting this  		 	*/
/*	algorithm.							*/
/*----------------------------------------------------------------------*/

#define yA  	0xf0
#define yB	0xcc
#define yC	0xaa
#define nA	0x0f
#define nB 	0x33
#define nC	0x55

UBYTE mints[4] = 
    { nA&nB&yC, nA&yB&yC, yA&nB&yC,  yA&yB&yC };

UBYTE mints4P[2] = {nB&yC, yB&yC};

#ifdef DBUG
dbgmask(msk,bpr,h) UBYTE  *msk; int bpr,h; {
    struct RastPort rp;
    InitRastPort(&rp);
    rp.BitMap = canvas.bm;
    SetAPen(&rp,1);
    SetBPen(&rp,0);
    SetDrMd(&rp,JAM2);
    BltTemplate(msk,0,bpr,&rp,0,30,bpr*8,h);
    }
    
dbgbm(bm) struct BitMap *bm; {
BltBitMap(bm,0,0,canvas.bm,0,80,bm->BytesPerRow*8,bm->Rows,REPOP,0xff,NULL);
    }
#endif

void MaskRange(bm, mask, tmp, lower, upper)
    struct BitMap *bm;	/* bitmap for which mask is being created */
    UBYTE *mask;	/* to receive mask */
    UBYTE *tmp;		/* temp storage */
    int lower,upper;	/* defines range for mask */
    {
    int minterm, i, octstart, octend, lastInOct,oct,depth;
    int bpr = bm->BytesPerRow;
    int h = bm->Rows;
    int bltsize = BlitSize(bpr,h);
    
    octstart = lower>>3;
    octend = upper>>3;
    lastInOct = (octstart<<3)+7;
    depth = bm->Depth;
    
    for (oct = octstart; oct<=octend; oct++) {
	minterm = 0;
	/* find subset of ALL pixels whose lower order 3 bits 
		are in this octaves subrange */
	for (i = lower; i<= MIN(upper, lastInOct); ++i)
    		minterm |= ( 1 << (i&7) );

	BltABCD(bm->Planes[2],bm->Planes[1],bm->Planes[0],tmp, bltsize, minterm);

	/* filter out the pixels not in this 8 color "octave" */
	
	if (depth==5) 
	  BltABCD(bm->Planes[4],bm->Planes[3], tmp, tmp, bltsize, mints[oct]);
	else if (depth==4)
	  BltABCD(NULL,bm->Planes[3], tmp, tmp, bltsize, mints4P[oct]);

	/* OR in to mask being built up */
	BltABCD(tmp,mask,NULL,mask, bltsize, (oct==octstart)?yA : yA|yB);

	lower = lastInOct+1;
	lastInOct += 8;
	}	    
    }


#ifdef newway
    
ShadePaint(sbm, spos, mask, dbm, dpos, copyBox, incop,tmpbuf) 
    struct BitMap *sbm;
    Point *spos;
    UBYTE *mask;
    struct BitMap *dbm;
    Point *dpos;
    Box *copyBox;
    UBYTE incop;		
    UBYTE *tmpbuf; 
    {
    struct BitMap tmp,carry;
    int i, depth;
    int sx,sy,dx,dy,w,h;
    PLANEPTR svp0;
    sx = copyBox->x - spos->x;    sy = copyBox->y - spos->y;
    dx = copyBox->x - dpos->x;    dy = copyBox->y - dpos->y;
    w = copyBox->w;    h = copyBox->h;
    depth = dbm->Depth;
    dbm->Depth = 1;
    svp0 = dbm->Planes[0];
    InitBitMap(&carry,1,sbm->BytesPerRow*8, sbm->Rows);
    carry.Planes[0] = tmpbuf;
    tmp = carry;
    tmp.Planes[0] = mask;
    BltBitMap(&tmp,sx,sy,&carry,sx,sy,w,h,ANDOP,0xff,NULL);
    WaitBlit();
    for (i = 0; i< depth; i++) {
	dbm->Planes[0] = dbm->Planes[i];
	BltBitMap(&carry,sx,sy,dbm,dx,dy,w,h, XOROP, 0xff, NULL);
	WaitBlit();
	BltBitMap(dbm,dx,dy,&carry,sx,sy,w,h, incop, 0xff, NULL);
	WaitBlit();
	}
    dbm->Planes[0] = svp0;
    dbm->Depth = depth;
    }

#else

ShadePaint(sbm, mask, sx, sy, dbm, dx, dy, w,h, incop,tmpbuf) 
    struct BitMap *sbm;
    UBYTE *mask;
    SHORT sx,sy;
    struct BitMap *dbm;
    SHORT dx,dy,w,h;
    UBYTE incop;		
    UBYTE *tmpbuf; 
    {
    struct BitMap tmp,carry;
    int i, depth;
    PLANEPTR svp0;
    
    depth = dbm->Depth;
    dbm->Depth = 1;
    svp0 = dbm->Planes[0];
    InitBitMap(&carry,1,sbm->BytesPerRow*8, sbm->Rows);
    carry.Planes[0] = tmpbuf;
    tmp = carry;
    tmp.Planes[0] = mask;
    BltBitMap(&tmp,sx,sy,&carry,sx,sy,w,h,ANDOP,0xff,NULL);
    WaitBlit();
    for (i = 0; i< depth; i++) {
	dbm->Planes[0] = dbm->Planes[i];
	BltBitMap(&carry,sx,sy,dbm,dx,dy,w,h, XOROP, 0xff, NULL);
	WaitBlit();
	BltBitMap(dbm,dx,dy,&carry,sx,sy,w,h, incop, 0xff, NULL);
	WaitBlit();
	}
    dbm->Planes[0] = svp0;
    dbm->Depth = depth;
    }
#endif