⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gview.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
void recenter_disp(Point c){	transform tr = cur_trans();	fpoint cc, off;	do_untransform(&cc, &tr, &c);	off.x = cc.x - .5*(univ.disp.min.x + univ.disp.max.x);	off.y = cc.y - .5*(univ.disp.min.y + univ.disp.max.y);	univ.disp.min.x += off.x;	univ.disp.min.y += off.y;	univ.disp.max.x += off.x;	univ.disp.max.y += off.y;}/* Find the upper-left and lower-right corners of the bounding box of the   parallelogram formed by untransforming the rectangle rminx, rminy, ... (given   in screen coordinates), and return the height of the parallelogram (negated   if it slopes downward).*/double untransform_corners(double rminx, double rminy, double rmaxx, double rmaxy,		fpoint *ul, fpoint *lr){	fpoint r_ur, r_ul, r_ll, r_lr;	/* corners of the given recangle */	fpoint ur, ll;			/* untransformed versions of r_ur, r_ll */	transform tr = cur_trans();	double ht;	r_ur.x=rmaxx;  r_ur.y=rminy;	r_ul.x=rminx;  r_ul.y=rminy;	r_ll.x=rminx;  r_ll.y=rmaxy;	r_lr.x=rmaxx;  r_lr.y=rmaxy;	do_untransform(ul, &tr, &r_ul);	do_untransform(lr, &tr, &r_lr);	do_untransform(&ur, &tr, &r_ur);	do_untransform(&ll, &tr, &r_ll);	ht = ur.y - lr->y;	if (ll.x < ul->x)		ul->x = ll.x;	if (ur.y > ul->y)		ul->y = ur.y;	else	ht = -ht;	if (ur.x > lr->x)		lr->x = ur.x;	if (ll.y < lr->y)		lr->y = ll.y;	return ht;}void disp_dozoom(double rminx, double rminy, double rmaxx, double rmaxy){	fpoint ul, lr;	double sh = untransform_corners(rminx, rminy, rmaxx, rmaxy, &ul, &lr);	if (ul.x==lr.x || ul.y==lr.y)		return;	univ.slant_ht = sh;	univ.disp.min.x = ul.x;	univ.disp.max.y = ul.y;	univ.disp.max.x = lr.x;	univ.disp.min.y = lr.y;	nontrivial_interval(&univ.disp.min.x, &univ.disp.max.x);	nontrivial_interval(&univ.disp.min.y, &univ.disp.max.y);}void disp_zoomin(Rectangle r){	disp_dozoom(r.min.x, r.min.y, r.max.x, r.max.y);}void disp_zoomout(Rectangle r){	double qminx, qminy, qmaxx, qmaxy;	double scx, scy;	Rectangle s = screen->r;	if (r.min.x==r.max.x || r.min.y==r.max.y)		return;	s.min.x += lft_border;	s.min.y += top_border;	s.max.x -= rt_border;	s.max.y -= bot_border;	scx = (s.max.x - s.min.x)/(r.max.x - r.min.x);	scy = (s.max.y - s.min.y)/(r.max.y - r.min.y);	qminx = s.min.x + scx*(s.min.x - r.min.x);	qmaxx = s.max.x + scx*(s.max.x - r.max.x);	qminy = s.min.y + scy*(s.min.y - r.min.y);	qmaxy = s.max.y + scy*(s.max.y - r.max.y);	disp_dozoom(qminx, qminy, qmaxx, qmaxy);}void expand2(double* a, double* b, double f){	double mid = .5*(*a + *b);	*a = mid + f*(*a - mid);	*b = mid + f*(*b - mid);}void disp_squareup(void){	double dx = univ.disp.max.x - univ.disp.min.x;	double dy = univ.disp.max.y - univ.disp.min.y;	dx /= screen->r.max.x - lft_border - screen->r.min.x - rt_border;	dy /= screen->r.max.y - bot_border - screen->r.min.y - top_border;	if (dx > dy)		expand2(&univ.disp.min.y, &univ.disp.max.y, dx/dy);	else	expand2(&univ.disp.min.x, &univ.disp.max.x, dy/dx);	univ.slant_ht = univ.disp.max.y - univ.disp.min.y;}/* Slant so that p and q appear at the same height on the screen and the   screen contains the smallest possible superset of what its previous contents.*/void slant_disp(fpoint p, fpoint q){	double yll, ylr, yul, yur;	/* corner y coords of displayed parallelogram */	double sh, dy;	if (p.x == q.x)		return;	sh = univ.slant_ht;	if (sh > 0) {		yll=yul=univ.disp.min.y;  yul+=sh;		ylr=yur=univ.disp.max.y;  ylr-=sh;	} else {		yll=yul=univ.disp.max.y;  yll+=sh;		ylr=yur=univ.disp.min.y;  yur-=sh;	}	dy = (univ.disp.max.x-univ.disp.min.x)*(q.y - p.y)/(q.x - p.x);	dy -= ylr - yll;	if (dy > 0)		{yll-=dy; yur+=dy;}	else	{yul-=dy; ylr+=dy;}	if (ylr > yll) {		univ.disp.min.y = yll;		univ.disp.max.y = yur;		univ.slant_ht = yur - ylr;	} else {		univ.disp.max.y = yul;		univ.disp.min.y = ylr;		univ.slant_ht = ylr - yur;	}}/******************************** Ascii input  ********************************/void set_fbb(fpolygon* fp){	fpoint lo=fp->p[0], hi=fp->p[0];	const fpoint *q, *qtop;	for (qtop=(q=fp->p)+fp->n; ++q<=qtop;) {		if (q->x < lo.x) lo.x=q->x;		if (q->y < lo.y) lo.y=q->y;		if (q->x > hi.x) hi.x=q->x;		if (q->y > hi.y) hi.y=q->y;	}	fp->bb.min = lo;	fp->bb.max = hi;}char* mystrdup(char* s){	char *r, *t = strrchr(s,'"');	if (t==0) {		t = s + strlen(s);		while (t>s && (t[-1]=='\n' || t[-1]=='\r'))			t--;	}	r = malloc(1+(t-s));	memcpy(r, s, t-s);	r[t-s] = 0;	return r;}int is_valid_label(char* lab){	char* t;	if (lab[0]=='"')		return (t=strrchr(lab,'"'))!=0 && t!=lab && strspn(t+1," \t\r\n")==strlen(t+1);	return strcspn(lab," \t")==strlen(lab);}/* Read a polyline and update the number of lines read.  A zero result indicates bad   syntax if *lineno increases; otherwise it indicates end of file.*/fpolygon* rd_fpoly(FILE* fin, int *lineno){	char buf[256], junk[2];	fpoint q;	fpolygon* fp;	int allocn;	if (!fgets(buf,256,fin))		return 0;	(*lineno)++;	if (sscanf(buf,"%lg%lg%1s",&q.x,&q.y,junk) != 2)		return 0;	fp = malloc(sizeof(fpolygon));	allocn = 16;	fp->p = malloc(allocn*sizeof(fpoint));	fp->p[0] = q;	fp->n = 0;	fp->nam = "";	fp->thick = 0;	fp->clr = clr_im(DBlack);	while (fgets(buf,256,fin)) {		(*lineno)++;		if (sscanf(buf,"%lg%lg%1s",&q.x,&q.y,junk) != 2) {			if (!is_valid_label(buf))				{free(fp->p); free(fp); return 0;}			fp->nam = (buf[0]=='"') ? buf+1 : buf;			break;		}		if (++(fp->n) == allocn)			fp->p = realloc(fp->p, (allocn<<=1)*sizeof(fpoint));		fp->p[fp->n] = q;	}	fp->nam = mystrdup(fp->nam);	set_fbb(fp);	fp->link = 0;	return fp;}/* Read input into *fps and return 0 or a line number where there's a syntax error */int rd_fpolys(FILE* fin, fpolygons* fps){	fpolygon *fp, *fp0=fps->p;	int lineno=0, ok_upto=0;	while ((fp=rd_fpoly(fin,&lineno)) != 0) {		ok_upto = lineno;		fp->link = fps->p;		fps->p = fp;		grow_bb(&fps->bb, &fp->bb);	}	set_default_clrs(fps, fp0);	return (ok_upto==lineno) ? 0 : lineno;}/* Read input from file fnam and return an error line no., -1 for "can't open"   or 0 for success.*/int doinput(char* fnam){	FILE* fin = strcmp(fnam,"-")==0 ? stdin : fopen(fnam, "r");	int errline_or0;	if (fin==0)		return -1;	errline_or0 = rd_fpolys(fin, &univ);	fclose(fin);	return errline_or0;}/******************************** Ascii output ********************************/fpolygon* fp_reverse(fpolygon* fp){	fpolygon* r = 0;	while (fp!=0) {		fpolygon* q = fp->link;		fp->link = r;		r = fp;		fp = q;	}	return r;}void wr_fpoly(FILE* fout, const fpolygon* fp){	char buf[256];	int i;	for (i=0; i<=fp->n; i++)		fprintf(fout,"%.12g\t%.12g\n", fp->p[i].x, fp->p[i].y);	fprintf(fout,"\"%s\"\n", nam_with_thclr(fp->nam, fp->thick, fp->clr, buf, 256));}void wr_fpolys(FILE* fout, fpolygons* fps){	fpolygon* fp;	fps->p = fp_reverse(fps->p);	for (fp=fps->p; fp!=0; fp=fp->link)		wr_fpoly(fout, fp);	fps->p = fp_reverse(fps->p);}int dooutput(char* fnam){	FILE* fout = fopen(fnam, "w");	if (fout==0)		return 0;	wr_fpolys(fout, &univ);	fclose(fout);	return 1;}/************************ Clipping to screen rectangle ************************//* Find the t values, 0<=t<=1 for which x0+t*(x1-x0) is between xlo and xhi,   or return 0 to indicate no such t values exist.  If returning 1, set *t0 and   *t1 to delimit the t interval.*/int do_xory(double x0, double x1, double xlo, double xhi, double* t0, double* t1){	*t1 = 1.0;	if (x0<xlo) {		if (x1<xlo) return 0;		*t0 = (xlo-x0)/(x1-x0);		if (x1>xhi) *t1 = (xhi-x0)/(x1-x0);	} else if (x0>xhi) {		if (x1>xhi) return 0;		*t0 = (xhi-x0)/(x1-x0);		if (x1<xlo) *t1 = (xlo-x0)/(x1-x0);	} else {		*t0 = 0.0;		if (x1>xhi) *t1 = (xhi-x0)/(x1-x0);		else if (x1<xlo) *t1 = (xlo-x0)/(x1-x0);		else *t1 = 1.0;	}	return 1;}/* After mapping y to y-slope*x, what initial fraction of the *p to *q edge is   outside of *r?  Note that the edge could start outside *r, pass through *r,   and wind up outside again.*/double frac_outside(const fpoint* p, const fpoint* q, const frectangle* r,		double slope){	double t0, t1, tt0, tt1;	double px=p->x, qx=q->x;	if (!do_xory(px, qx, r->min.x, r->max.x, &t0, &t1))		return 1;	if (!do_xory(p->y-slope*px, q->y-slope*qx, r->min.y, r->max.y, &tt0, &tt1))		return 1;	if (tt0 > t0)		t0 = tt0;	if (t1<=t0 || tt1<=t0)		return 1;	return t0;}/* Think of p0..pn as piecewise-linear function F(t) for t=0..pn-p0, and find   the maximum tt such that F(0..tt) is all inside of r, assuming p0 is inside.   Coordinates are transformed by y=y-x*slope before testing against r.*/double in_length(const fpoint* p0, const fpoint* pn, frectangle r, double slope){	const fpoint* p = p0;	double px, py;	do if (++p > pn)		return pn - p0;	while (r.min.x<=(px=p->x) && px<=r.max.x			&& r.min.y<=(py=p->y-slope*px) && py<=r.max.y);	return (p - p0) - frac_outside(p, p-1, &r, slope);}/* Think of p0..pn as piecewise-linear function F(t) for t=0..pn-p0, and find   the maximum tt such that F(0..tt) is all outside of *r.  Coordinates are   transformed by y=y-x*slope before testing against r.*/double out_length(const fpoint* p0, const fpoint* pn, frectangle r, double slope){	const fpoint* p = p0;	double fr;	do {	if (p->x < r.min.x)			do if (++p>pn) return pn-p0;			while (p->x <= r.min.x);		else if (p->x > r.max.x)			do if (++p>pn) return pn-p0;			while (p->x >= r.max.x);		else if (p->y-slope*p->x < r.min.y)			do if (++p>pn) return pn-p0;			while (p->y-slope*p->x <= r.min.y);		else if (p->y-slope*p->x > r.max.y)			do if (++p>pn) return pn-p0;			while (p->y-slope*p->x >= r.max.y);		else return p - p0;	} while ((fr=frac_outside(p-1,p,&r,slope)) == 1);	return (p - p0) + fr-1;}/*********************** Drawing frame and axis labels  ***********************/#define Nthous  7#define Len_thous  30			/* bound on strlen(thous_nam[i]) */char* thous_nam[Nthous] = {	"one", "thousand", "million", "billion",	"trillion", "quadrillion", "quintillion",};typedef struct lab_interval {	double sep;			/* separation between tick marks */	double unit;		/* power of 1000 divisor */	int logunit;		/* log base 1000 of of this divisor */	double off;			/* offset to subtract before dividing */} lab_interval;char* abbrev_num(double x, const lab_interval* iv){	static char buf[16];	double dx = x - iv->off;	dx = iv->sep * floor(dx/iv->sep + .5);	sprintf(buf,"%g", dx/iv->unit);	return buf;}double lead_digits(double n, double r)	/* n truncated to power of 10 above r */{	double rr = pow(10, ceil(log10(r)));	double nn = (n<rr) ? 0.0 : rr*floor(n/rr);	if (n+r-nn >= digs10pow) {		rr /= 10;		nn = (n<rr) ? 0.0 : rr*floor(n/rr);	}	return nn;}lab_interval next_larger(double s0, double xlo, double xhi){	double nlo, nhi;	lab_interval r;	r.logunit = (int) floor(log10(s0) + LOG2);	r.unit = pow(10, r.logunit);	nlo = xlo/r.unit;	nhi = xhi/r.unit;	if (nhi >= digs10pow)		r.off = r.unit*lead_digits(nlo, nhi-nlo);	else if (nlo <= -digs10pow)		r.off = -r.unit*lead_digits(-nhi, nhi-nlo);	else	r.off = 0;	r.sep = (s0<=r.unit) ? r.unit : (s0<2*r.unit ? 2*r.unit : 5*r.unit);	switch (r.logunit%3) {	case 1:	r.unit*=.1; r.logunit--;		break;	case -1: case 2:		r.unit*=10; r.logunit++;		break;	case -2: r.unit*=100; r.logunit+=2;	}	r.logunit /= 3;	return r;}double min_hsep(const transform* tr){	double s = (2+labdigs)*sdigit.x;	double ss = (univ.disp.min.x<0) ? s+sdigit.x : s;	return dxuntransform(tr, ss);}lab_interval mark_x_axis(const transform* tr){	fpoint p = univ.disp.min;	Point q, qtop, qbot, tmp;	double x0=univ.disp.min.x, x1=univ.disp.max.x;	double seps0, nseps, seps;	lab_interval iv = next_larger(min_hsep(tr), x0, x1);	set_unslanted_y(&univ, &p.y, 0);	q.y = ytransform(tr, p.y) + .5;	qtop.y = q.y - tick_len;	qbot.y = q.y + framewd + framesep;	seps0 = ceil(x0/iv.sep);	for (seps=0, nseps=floor(x1/iv.sep)-seps0; seps<=nseps; seps+=1) {		char* num = abbrev_num((p.x=iv.sep*(seps0+seps)), &iv);		Font* f = display->defaultfont;		q.x = qtop.x = qbot.x = xtransform(tr, p.x);		line(screen, qtop, q, Enddisc, Enddisc, 0, axis_color, q);		tmp = stringsize(f, num);		qbot.x -= tmp.x/2;		string(screen, qbot, display->black, qbot, f, num);	}	return iv;}lab_interval mark_y_axis(const transform* tr){	Font* f = display->defaultfont;	fpoint p = univ.disp.min;	Point q, qrt, qlft;	double y0, y1, seps0, nseps, seps;	lab_interval iv;	set_unslanted_y(&univ, &y0, &y1);	iv = next_larger(dyuntransform(tr,-f->height), y0, y1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -