Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/unix/drawterm/libmemdraw/line.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
#include <memdraw.h>
5
#include <memlayer.h>
6
 
7
enum
8
{
9
	Arrow1 = 8,
10
	Arrow2 = 10,
11
	Arrow3 = 3,
12
};
13
 
14
#ifdef NOT
15
static
16
int
17
lmin(int a, int b)
18
{
19
	if(a < b)
20
		return a;
21
	return b;
22
}
23
#endif
24
 
25
static
26
int
27
lmax(int a, int b)
28
{
29
	if(a > b)
30
		return a;
31
	return b;
32
}
33
 
34
#ifdef NOTUSED
35
/*
36
 * Rather than line clip, we run the Bresenham loop over the full line,
37
 * and clip on each pixel.  This is more expensive but means that
38
 * lines look the same regardless of how the windowing has tiled them.
39
 * For speed, we check for clipping outside the loop and make the
40
 * test easy when possible.
41
 */
42
 
43
static
44
void
45
horline1(Memimage *dst, Point p0, Point p1, int srcval, Rectangle clipr)
46
{
47
	int x, y, dy, deltay, deltax, maxx;
48
	int dd, easy, e, bpp, m, m0;
49
	uchar *d;
50
 
51
	deltax = p1.x - p0.x;
52
	deltay = p1.y - p0.y;
53
	dd = dst->width*sizeof(ulong);
54
	dy = 1;
55
	if(deltay < 0){
56
		dd = -dd;
57
		deltay = -deltay;
58
		dy = -1;
59
	}
60
	maxx = lmin(p1.x, clipr.max.x-1);
61
	bpp = dst->depth;
62
	m0 = 0xFF^(0xFF>>bpp);
63
	m = m0 >> (p0.x&(7/dst->depth))*bpp;
64
	easy = ptinrect(p0, clipr) && ptinrect(p1, clipr);
65
	e = 2*deltay - deltax;
66
	y = p0.y;
67
	d = byteaddr(dst, p0);
68
	deltay *= 2;
69
	deltax = deltay - 2*deltax;
70
	for(x=p0.x; x<=maxx; x++){
71
		if(easy || (clipr.min.x<=x && clipr.min.y<=y && y<clipr.max.y))
72
			*d ^= (*d^srcval) & m;
73
		if(e > 0){
74
			y += dy;
75
			d += dd;
76
			e += deltax;
77
		}else
78
			e += deltay;
79
		d++;
80
		m >>= bpp;
81
		if(m == 0)
82
			m = m0;
83
	}
84
}
85
 
86
static
87
void
88
verline1(Memimage *dst, Point p0, Point p1, int srcval, Rectangle clipr)
89
{
90
	int x, y, deltay, deltax, maxy;
91
	int easy, e, bpp, m, m0, dd;
92
	uchar *d;
93
 
94
	deltax = p1.x - p0.x;
95
	deltay = p1.y - p0.y;
96
	dd = 1;
97
	if(deltax < 0){
98
		dd = -1;
99
		deltax = -deltax;
100
	}
101
	maxy = lmin(p1.y, clipr.max.y-1);
102
	bpp = dst->depth;
103
	m0 = 0xFF^(0xFF>>bpp);
104
	m = m0 >> (p0.x&(7/dst->depth))*bpp;
105
	easy = ptinrect(p0, clipr) && ptinrect(p1, clipr);
106
	e = 2*deltax - deltay;
107
	x = p0.x;
108
	d = byteaddr(dst, p0);
109
	deltax *= 2;
110
	deltay = deltax - 2*deltay;
111
	for(y=p0.y; y<=maxy; y++){
112
		if(easy || (clipr.min.y<=y && clipr.min.x<=x && x<clipr.max.x))
113
			*d ^= (*d^srcval) & m;
114
		if(e > 0){
115
			x += dd;
116
			d += dd;
117
			e += deltay;
118
		}else
119
			e += deltax;
120
		d += dst->width*sizeof(ulong);
121
		m >>= bpp;
122
		if(m == 0)
123
			m = m0;
124
	}
125
}
126
 
127
static
128
void
129
horliner(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr)
130
{
131
	int x, y, sx, sy, deltay, deltax, minx, maxx;
132
	int bpp, m, m0;
133
	uchar *d, *s;
134
 
135
	deltax = p1.x - p0.x;
136
	deltay = p1.y - p0.y;
137
	sx = drawreplxy(src->r.min.x, src->r.max.x, p0.x+dsrc.x);
138
	minx = lmax(p0.x, clipr.min.x);
139
	maxx = lmin(p1.x, clipr.max.x-1);
140
	bpp = dst->depth;
141
	m0 = 0xFF^(0xFF>>bpp);
142
	m = m0 >> (minx&(7/dst->depth))*bpp;
143
	for(x=minx; x<=maxx; x++){
144
		y = p0.y + (deltay*(x-p0.x)+deltax/2)/deltax;
145
		if(clipr.min.y<=y && y<clipr.max.y){
146
			d = byteaddr(dst, Pt(x, y));
147
			sy = drawreplxy(src->r.min.y, src->r.max.y, y+dsrc.y);
148
			s = byteaddr(src, Pt(sx, sy));
149
			*d ^= (*d^*s) & m;
150
		}
151
		if(++sx >= src->r.max.x)
152
			sx = src->r.min.x;
153
		m >>= bpp;
154
		if(m == 0)
155
			m = m0;
156
	}
157
}
158
 
159
static
160
void
161
verliner(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr)
162
{
163
	int x, y, sx, sy, deltay, deltax, miny, maxy;
164
	int bpp, m, m0;
165
	uchar *d, *s;
166
 
167
	deltax = p1.x - p0.x;
168
	deltay = p1.y - p0.y;
169
	sy = drawreplxy(src->r.min.y, src->r.max.y, p0.y+dsrc.y);
170
	miny = lmax(p0.y, clipr.min.y);
171
	maxy = lmin(p1.y, clipr.max.y-1);
172
	bpp = dst->depth;
173
	m0 = 0xFF^(0xFF>>bpp);
174
	for(y=miny; y<=maxy; y++){
175
		if(deltay == 0)	/* degenerate line */
176
			x = p0.x;
177
		else
178
			x = p0.x + (deltax*(y-p0.y)+deltay/2)/deltay;
179
		if(clipr.min.x<=x && x<clipr.max.x){
180
			m = m0 >> (x&(7/dst->depth))*bpp;
181
			d = byteaddr(dst, Pt(x, y));
182
			sx = drawreplxy(src->r.min.x, src->r.max.x, x+dsrc.x);
183
			s = byteaddr(src, Pt(sx, sy));
184
			*d ^= (*d^*s) & m;
185
		}
186
		if(++sy >= src->r.max.y)
187
			sy = src->r.min.y;
188
	}
189
}
190
 
191
static
192
void
193
horline(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr)
194
{
195
	int x, y, deltay, deltax, minx, maxx;
196
	int bpp, m, m0;
197
	uchar *d, *s;
198
 
199
	deltax = p1.x - p0.x;
200
	deltay = p1.y - p0.y;
201
	minx = lmax(p0.x, clipr.min.x);
202
	maxx = lmin(p1.x, clipr.max.x-1);
203
	bpp = dst->depth;
204
	m0 = 0xFF^(0xFF>>bpp);
205
	m = m0 >> (minx&(7/dst->depth))*bpp;
206
	for(x=minx; x<=maxx; x++){
207
		y = p0.y + (deltay*(x-p0.x)+deltay/2)/deltax;
208
		if(clipr.min.y<=y && y<clipr.max.y){
209
			d = byteaddr(dst, Pt(x, y));
210
			s = byteaddr(src, addpt(dsrc, Pt(x, y)));
211
			*d ^= (*d^*s) & m;
212
		}
213
		m >>= bpp;
214
		if(m == 0)
215
			m = m0;
216
	}
217
}
218
 
219
static
220
void
221
verline(Memimage *dst, Point p0, Point p1, Memimage *src, Point dsrc, Rectangle clipr)
222
{
223
	int x, y, deltay, deltax, miny, maxy;
224
	int bpp, m, m0;
225
	uchar *d, *s;
226
 
227
	deltax = p1.x - p0.x;
228
	deltay = p1.y - p0.y;
229
	miny = lmax(p0.y, clipr.min.y);
230
	maxy = lmin(p1.y, clipr.max.y-1);
231
	bpp = dst->depth;
232
	m0 = 0xFF^(0xFF>>bpp);
233
	for(y=miny; y<=maxy; y++){
234
		if(deltay == 0)	/* degenerate line */
235
			x = p0.x;
236
		else
237
			x = p0.x + deltax*(y-p0.y)/deltay;
238
		if(clipr.min.x<=x && x<clipr.max.x){
239
			m = m0 >> (x&(7/dst->depth))*bpp;
240
			d = byteaddr(dst, Pt(x, y));
241
			s = byteaddr(src, addpt(dsrc, Pt(x, y)));
242
			*d ^= (*d^*s) & m;
243
		}
244
	}
245
}
246
#endif /* NOTUSED */
247
 
248
static Memimage*
249
membrush(int radius)
250
{
251
	static Memimage *brush;
252
	static int brushradius;
253
 
254
	if(brush==nil || brushradius!=radius){
255
		freememimage(brush);
256
		brush = allocmemimage(Rect(0, 0, 2*radius+1, 2*radius+1), memopaque->chan);
257
		if(brush != nil){
258
			memfillcolor(brush, DTransparent);	/* zeros */
259
			memellipse(brush, Pt(radius, radius), radius, radius, -1, memopaque, Pt(radius, radius), S);
260
		}
261
		brushradius = radius;
262
	}
263
	return brush;
264
}
265
 
266
static
267
void
268
discend(Point p, int radius, Memimage *dst, Memimage *src, Point dsrc, int op)
269
{
270
	Memimage *disc;
271
	Rectangle r;
272
 
273
	disc = membrush(radius);
274
	if(disc != nil){
275
		r.min.x = p.x - radius;
276
		r.min.y = p.y - radius;
277
		r.max.x = p.x + radius+1;
278
		r.max.y = p.y + radius+1;
279
		memdraw(dst, r, src, addpt(r.min, dsrc), disc, Pt(0,0), op);
280
	}
281
}
282
 
283
static
284
void
285
arrowend(Point tip, Point *pp, int end, int sin, int cos, int radius)
286
{
287
	int x1, x2, x3;
288
 
289
	/* before rotation */
290
	if(end == Endarrow){
291
		x1 = Arrow1;
292
		x2 = Arrow2;
293
		x3 = Arrow3;
294
	}else{
295
		x1 = (end>>5) & 0x1FF;	/* distance along line from end of line to tip */
296
		x2 = (end>>14) & 0x1FF;	/* distance along line from barb to tip */
297
		x3 = (end>>23) & 0x1FF;	/* distance perpendicular from edge of line to barb */
298
	}
299
 
300
	/* comments follow track of right-facing arrowhead */
301
	pp->x = tip.x+((2*radius+1)*sin/2-x1*cos);		/* upper side of shaft */
302
	pp->y = tip.y-((2*radius+1)*cos/2+x1*sin);
303
	pp++;
304
	pp->x = tip.x+((2*radius+2*x3+1)*sin/2-x2*cos);		/* upper barb */
305
	pp->y = tip.y-((2*radius+2*x3+1)*cos/2+x2*sin);
306
	pp++;
307
	pp->x = tip.x;
308
	pp->y = tip.y;
309
	pp++;
310
	pp->x = tip.x+(-(2*radius+2*x3+1)*sin/2-x2*cos);	/* lower barb */
311
	pp->y = tip.y-(-(2*radius+2*x3+1)*cos/2+x2*sin);
312
	pp++;
313
	pp->x = tip.x+(-(2*radius+1)*sin/2-x1*cos);		/* lower side of shaft */
314
	pp->y = tip.y+((2*radius+1)*cos/2-x1*sin);
315
}
316
 
317
void
318
_memimageline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr, int op)
319
{
320
	/*
321
	 * BUG: We should really really pick off purely horizontal and purely
322
	 * vertical lines and handle them separately with calls to memimagedraw
323
	 * on rectangles.
324
	 */
325
 
326
	int hor;
327
	int sin, cos, dx, dy, t;
328
	Rectangle oclipr, r;
329
	Point q, pts[10], *pp, d;
330
 
331
	if(radius < 0)
332
		return;
333
	if(rectclip(&clipr, dst->r) == 0)
334
		return;
335
	if(rectclip(&clipr, dst->clipr) == 0)
336
		return;
337
	d = subpt(sp, p0);
338
	if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0)
339
		return;
340
	if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0)
341
		return;
342
	/* this means that only verline() handles degenerate lines (p0==p1) */
343
	hor = (abs(p1.x-p0.x) > abs(p1.y-p0.y));
344
	/*
345
	 * Clipping is a little peculiar.  We can't use Sutherland-Cohen
346
	 * clipping because lines are wide.  But this is probably just fine:
347
	 * we do all math with the original p0 and p1, but clip when deciding
348
	 * what pixels to draw.  This means the layer code can call this routine,
349
	 * using clipr to define the region being written, and get the same set
350
	 * of pixels regardless of the dicing.
351
	 */
352
	if((hor && p0.x>p1.x) || (!hor && p0.y>p1.y)){
353
		q = p0;
354
		p0 = p1;
355
		p1 = q;
356
		t = end0;
357
		end0 = end1;
358
		end1 = t;
359
	}
360
 
361
	if((p0.x == p1.x || p0.y == p1.y) && (end0&0x1F) == Endsquare && (end1&0x1F) == Endsquare){
362
		r.min = p0;
363
		r.max = p1;
364
		if(p0.x == p1.x){
365
			r.min.x -= radius;
366
			r.max.x += radius+1;
367
		}
368
		else{
369
			r.min.y -= radius;
370
			r.max.y += radius+1;
371
		}
372
		oclipr = dst->clipr;
373
		dst->clipr = clipr;
374
		memimagedraw(dst, r, src, sp, memopaque, sp, op);
375
		dst->clipr = oclipr;
376
		return;
377
	}
378
 
379
/*    Hard: */
380
	/* draw thick line using polygon fill */
381
	icossin2(p1.x-p0.x, p1.y-p0.y, &cos, &sin);
382
	dx = (sin*(2*radius+1))/2;
383
	dy = (cos*(2*radius+1))/2;
384
	pp = pts;
385
	oclipr = dst->clipr;
386
	dst->clipr = clipr;
387
	q.x = ICOSSCALE*p0.x+ICOSSCALE/2-cos/2;
388
	q.y = ICOSSCALE*p0.y+ICOSSCALE/2-sin/2;
389
	switch(end0 & 0x1F){
390
	case Enddisc:
391
		discend(p0, radius, dst, src, d, op);
392
		/* fall through */
393
	case Endsquare:
394
	default:
395
		pp->x = q.x-dx;
396
		pp->y = q.y+dy;
397
		pp++;
398
		pp->x = q.x+dx;
399
		pp->y = q.y-dy;
400
		pp++;
401
		break;
402
	case Endarrow:
403
		arrowend(q, pp, end0, -sin, -cos, radius);
404
		_memfillpolysc(dst, pts, 5, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 1, 10, 1, op);
405
		pp[1] = pp[4];
406
		pp += 2;
407
	}
408
	q.x = ICOSSCALE*p1.x+ICOSSCALE/2+cos/2;
409
	q.y = ICOSSCALE*p1.y+ICOSSCALE/2+sin/2;
410
	switch(end1 & 0x1F){
411
	case Enddisc:
412
		discend(p1, radius, dst, src, d, op);
413
		/* fall through */
414
	case Endsquare:
415
	default:
416
		pp->x = q.x+dx;
417
		pp->y = q.y-dy;
418
		pp++;
419
		pp->x = q.x-dx;
420
		pp->y = q.y+dy;
421
		pp++;
422
		break;
423
	case Endarrow:
424
		arrowend(q, pp, end1, sin, cos, radius);
425
		_memfillpolysc(dst, pp, 5, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 1, 10, 1, op);
426
		pp[1] = pp[4];
427
		pp += 2;
428
	}
429
	_memfillpolysc(dst, pts, pp-pts, ~0, src, addpt(pts[0], mulpt(d, ICOSSCALE)), 0, 10, 1, op);
430
	dst->clipr = oclipr;
431
	return;
432
}
433
 
434
void
435
memimageline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, int op)
436
{
437
	_memimageline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr, op);
438
}
439
 
440
/*
441
 * Simple-minded conservative code to compute bounding box of line.
442
 * Result is probably a little larger than it needs to be.
443
 */
444
static
445
void
446
addbbox(Rectangle *r, Point p)
447
{
448
	if(r->min.x > p.x)
449
		r->min.x = p.x;
450
	if(r->min.y > p.y)
451
		r->min.y = p.y;
452
	if(r->max.x < p.x+1)
453
		r->max.x = p.x+1;
454
	if(r->max.y < p.y+1)
455
		r->max.y = p.y+1;
456
}
457
 
458
int
459
memlineendsize(int end)
460
{
461
	int x3;
462
 
463
	if((end&0x3F) != Endarrow)
464
		return 0;
465
	if(end == Endarrow)
466
		x3 = Arrow3;
467
	else
468
		x3 = (end>>23) & 0x1FF;
469
	return x3;
470
}
471
 
472
Rectangle
473
memlinebbox(Point p0, Point p1, int end0, int end1, int radius)
474
{
475
	Rectangle r, r1;
476
	int extra;
477
 
478
	r.min.x = 10000000;
479
	r.min.y = 10000000;
480
	r.max.x = -10000000;
481
	r.max.y = -10000000;
482
	extra = lmax(memlineendsize(end0), memlineendsize(end1));
483
	r1 = insetrect(canonrect(Rpt(p0, p1)), -(radius+extra));
484
	addbbox(&r, r1.min);
485
	addbbox(&r, r1.max);
486
	return r;
487
}