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

📄 miarc.c

📁 linux下电话本所依赖的一些图形库
💻 C
📖 第 1 页 / 共 5 页
字号:
		yMin = MIN (yMin, parc->y);		xMax = MAX (xMax, (parc->x + (int) parc->width));		yMax = MAX (yMax, (parc->y + (int) parc->height));	    }	    /* expand box to deal with line widths */	    halfWidth = (width + 1)/2;	    xMin -= halfWidth;	    yMin -= halfWidth;	    xMax += halfWidth;	    yMax += halfWidth;	    /* compute pixmap size; limit it to size of drawable */	    xOrg = MAX(xMin, 0);	    yOrg = MAX(yMin, 0);	    pixmapWidth = MIN(xMax, GDK_DRAWABLE_FBDATA(pDraw)->width) - xOrg;	    pixmapHeight = MIN(yMax, GDK_DRAWABLE_FBDATA(pDraw)->height) - yOrg;	    /* if nothing left, return */	    if ( (pixmapWidth <= 0) || (pixmapHeight <= 0) ) return;	    for(i = narcs, parc = parcs; --i >= 0; parc++)	    {		parc->x -= xOrg;		parc->y -= yOrg;	    }	    /* set up scratch GC */	    /* allocate a 1 bit deep pixmap of the appropriate size, and	     * validate it */	    pDrawTo = gdk_pixmap_new(NULL, pixmapWidth, pixmapHeight, 1);	    if (!pDrawTo)	      return;	    pGCTo = gdk_gc_new(pDrawTo);	    if (!pGCTo)	      {		gdk_pixmap_unref(pDrawTo);		return;	      }	    gdk_gc_set_function(pGCTo, GDK_COPY);	    memset(&gcv.background, 0, sizeof(GdkColor));	    gcv.foreground.pixel = 1;	    gcv.foreground.red = gcv.foreground.green = gcv.foreground.blue = 1;	    gdk_gc_set_foreground(pGCTo, &gcv.foreground);	    gdk_gc_set_background(pGCTo, &gcv.background);	    gdk_gc_set_line_attributes(pGCTo,				       GDK_GC_FBDATA(pGC)->values.line_width,				       GDK_GC_FBDATA(pGC)->values.line_style,				       GDK_GC_FBDATA(pGC)->values.cap_style,				       GDK_GC_FBDATA(pGC)->values.join_style);	    gdk_fb_drawable_clear(pDrawTo);	}	fg = GDK_GC_FBDATA(pGC)->values.foreground;	bg = GDK_GC_FBDATA(pGC)->values.background;	if ((GDK_GC_FBDATA(pGC)->values.fill == GDK_TILED) ||	    (GDK_GC_FBDATA(pGC)->values.fill == GDK_OPAQUE_STIPPLED))	    bg = fg; /* the protocol sez these don't cause color changes */	polyArcs = miComputeArcs (parcs, narcs, pGC);	if (!polyArcs)	{	    if (fTricky) {	      gdk_pixmap_unref(pDrawTo);	      gdk_gc_unref(pGCTo);	    }	    return;	}	cap[0] = cap[1] = 0;	join[0] = join[1] = 0;	for (iphase = ((GDK_GC_FBDATA(pGC)->values.line_style == GDK_LINE_DOUBLE_DASH) ? 1 : 0); 	     iphase >= 0;	     iphase--)	{	    if (iphase == 1)	      gdk_gc_set_foreground(pGC, &bg);	    else if (GDK_GC_FBDATA(pGC)->values.line_style == GDK_LINE_DOUBLE_DASH)	      gdk_gc_set_foreground(pGC, &fg);	    for (i = 0; i < polyArcs[iphase].narcs; i++) {		miArcDataPtr	arcData;		arcData = &polyArcs[iphase].arcs[i];		miArcSegment(pDrawTo, pGCTo, arcData->arc,			     &arcData->bounds[RIGHT_END],			     &arcData->bounds[LEFT_END]);		if (polyArcs[iphase].arcs[i].render) {		    fillSpans (pDrawTo, pGCTo);		    /*		     * don't cap self-joining arcs		     */		    if (polyArcs[iphase].arcs[i].selfJoin &&		        cap[iphase] < polyArcs[iphase].arcs[i].cap)		    	cap[iphase]++;		    while (cap[iphase] < polyArcs[iphase].arcs[i].cap) {			int	arcIndex, end;			miArcDataPtr	arcData0;			arcIndex = polyArcs[iphase].caps[cap[iphase]].arcIndex;			end = polyArcs[iphase].caps[cap[iphase]].end;			arcData0 = &polyArcs[iphase].arcs[arcIndex];			miArcCap (pDrawTo, pGCTo, 				  &arcData0->bounds[end], end,				  arcData0->arc.x, arcData0->arc.y,				  (double) arcData0->arc.width / 2.0, 				  (double) arcData0->arc.height / 2.0);			++cap[iphase];		    }		    while (join[iphase] < polyArcs[iphase].arcs[i].join) {			int	arcIndex0, arcIndex1, end0, end1;			int	phase0, phase1;			miArcDataPtr	arcData0, arcData1;			miArcJoinPtr	joinp;			joinp = &polyArcs[iphase].joins[join[iphase]];			arcIndex0 = joinp->arcIndex0;			end0 = joinp->end0;			arcIndex1 = joinp->arcIndex1;			end1 = joinp->end1;			phase0 = joinp->phase0;			phase1 = joinp->phase1;			arcData0 = &polyArcs[phase0].arcs[arcIndex0];			arcData1 = &polyArcs[phase1].arcs[arcIndex1];			miArcJoin (pDrawTo, pGCTo,				  &arcData0->bounds[end0], 				  &arcData1->bounds[end1],				  arcData0->arc.x, arcData0->arc.y,				  (double) arcData0->arc.width / 2.0, 				  (double) arcData0->arc.height / 2.0,				  arcData1->arc.x, arcData1->arc.y,				  (double) arcData1->arc.width / 2.0, 				  (double) arcData1->arc.height / 2.0);			++join[iphase];		    }		    if (fTricky) {		      gdk_fb_draw_drawable(pDraw, pGC, pDrawTo, 0, 0, xOrg, yOrg, pixmapWidth, pixmapHeight);		      gdk_fb_drawable_clear(pDrawTo);		    }		}	    }	}	miFreeArcs(polyArcs, pGC);	if(fTricky)	{	  gdk_pixmap_unref(pDrawTo);	  gdk_gc_unref(pGCTo);	}    }}static doubleangleBetween (SppPointRec center, SppPointRec point1, SppPointRec point2){	double	a1, a2, a;		/*	 * reflect from X coordinates back to ellipse	 * coordinates -- y increasing upwards	 */	a1 = miDatan2 (- (point1.y - center.y), point1.x - center.x);	a2 = miDatan2 (- (point2.y - center.y), point2.x - center.x);	a = a2 - a1;	if (a <= -180.0)		a += 360.0;	else if (a > 180.0)		a -= 360.0;	return a;}static voidtranslateBounds (miArcFacePtr b, int x, int y, double fx, double fy){	fx += x;	fy += y;	b->clock.x -= fx;	b->clock.y -= fy;	b->center.x -= fx;	b->center.y -= fy;	b->counterClock.x -= fx;	b->counterClock.y -= fy;}static voidmiArcJoin (GdkDrawable *pDraw, GdkGC *pGC, miArcFacePtr pLeft, miArcFacePtr pRight,	   int xOrgLeft, int yOrgLeft, double xFtransLeft, double yFtransLeft,	   int xOrgRight, int yOrgRight, double xFtransRight, double yFtransRight){	SppPointRec	center, corner, otherCorner;	SppPointRec	poly[5], e;	SppPointPtr	pArcPts;	int		cpt;	SppArcRec	arc;	miArcFaceRec	Right, Left;	int		polyLen = 0;	int		xOrg, yOrg;	double		xFtrans, yFtrans;	double		a;	double		ae, ac2, ec2, bc2, de;	double		width;		xOrg = (xOrgRight + xOrgLeft) / 2;	yOrg = (yOrgRight + yOrgLeft) / 2;	xFtrans = (xFtransLeft + xFtransRight) / 2;	yFtrans = (yFtransLeft + yFtransRight) / 2;	Right = *pRight;	translateBounds (&Right, xOrg - xOrgRight, yOrg - yOrgRight,				 xFtrans - xFtransRight, yFtrans - yFtransRight);	Left = *pLeft;	translateBounds (&Left, xOrg - xOrgLeft, yOrg - yOrgLeft,				 xFtrans - xFtransLeft, yFtrans - yFtransLeft);	pRight = &Right;	pLeft = &Left;	if (pRight->clock.x == pLeft->counterClock.x &&	    pRight->clock.y == pLeft->counterClock.y)		return;	center = pRight->center;	if (0 <= (a = angleBetween (center, pRight->clock, pLeft->counterClock)) 	    && a <= 180.0) 	{		corner = pRight->clock;		otherCorner = pLeft->counterClock;	} else {		a = angleBetween (center, pLeft->clock, pRight->counterClock);		corner = pLeft->clock;		otherCorner = pRight->counterClock;	}	switch (GDK_GC_FBDATA(pGC)->values.join_style) {	case GDK_JOIN_ROUND:		width = (GDK_GC_FBDATA(pGC)->values.line_width ? (double)GDK_GC_FBDATA(pGC)->values.line_width : (double)1);		arc.x = center.x - width/2;		arc.y = center.y - width/2;		arc.width = width;		arc.height = width;		arc.angle1 = -miDatan2 (corner.y - center.y, corner.x - center.x);		arc.angle2 = a;		pArcPts = (SppPointPtr) g_malloc (3 * sizeof (SppPointRec));		if (!pArcPts)		    return;		pArcPts[0].x = otherCorner.x;		pArcPts[0].y = otherCorner.y;		pArcPts[1].x = center.x;		pArcPts[1].y = center.y;		pArcPts[2].x = corner.x;		pArcPts[2].y = corner.y;		if( (cpt = miGetArcPts(&arc, 3, &pArcPts)) )		{			/* by drawing with miFillSppPoly and setting the endpoints of the arc			 * to be the corners, we assure that the cap will meet up with the			 * rest of the line */			miFillSppPoly(pDraw, pGC, cpt, pArcPts, xOrg, yOrg, xFtrans, yFtrans);		}		g_free(pArcPts);		return;	case GDK_JOIN_MITER:		/*		 * don't miter arcs with less than 11 degrees between them		 */		if (a < 169.0) {			poly[0] = corner;			poly[1] = center;			poly[2] = otherCorner;			bc2 = (corner.x - otherCorner.x) * (corner.x - otherCorner.x) +			      (corner.y - otherCorner.y) * (corner.y - otherCorner.y);			ec2 = bc2 / 4;			ac2 = (corner.x - center.x) * (corner.x - center.x) +			      (corner.y - center.y) * (corner.y - center.y);			ae = sqrt (ac2 - ec2);			de = ec2 / ae;			e.x = (corner.x + otherCorner.x) / 2;			e.y = (corner.y + otherCorner.y) / 2;			poly[3].x = e.x + de * (e.x - center.x) / ae;			poly[3].y = e.y + de * (e.y - center.y) / ae;			poly[4] = corner;			polyLen = 5;			break;		}	case GDK_JOIN_BEVEL:		poly[0] = corner;		poly[1] = center;		poly[2] = otherCorner;		poly[3] = corner;		polyLen = 4;		break;	}	miFillSppPoly (pDraw, pGC, polyLen, poly, xOrg, yOrg, xFtrans, yFtrans);}/*ARGSUSED*/static voidmiArcCap (GdkDrawable *pDraw, GdkGC *pGC, miArcFacePtr pFace, int end,          int xOrg, int yOrg, double xFtrans, double yFtrans){	SppPointRec	corner, otherCorner, center, endPoint, poly[5];	corner = pFace->clock;	otherCorner = pFace->counterClock;	center = pFace->center;	switch (GDK_GC_FBDATA(pGC)->values.cap_style) {	case GDK_CAP_PROJECTING:		poly[0].x = otherCorner.x;		poly[0].y = otherCorner.y;		poly[1].x = corner.x;		poly[1].y = corner.y;		poly[2].x = corner.x - 				(center.y - corner.y);		poly[2].y = corner.y + 				(center.x - corner.x);		poly[3].x = otherCorner.x - 				(otherCorner.y - center.y);		poly[3].y = otherCorner.y + 				(otherCorner.x - center.x);		poly[4].x = otherCorner.x;		poly[4].y = otherCorner.y;		miFillSppPoly (pDraw, pGC, 5, poly, xOrg, yOrg, xFtrans, yFtrans);		break;	case GDK_CAP_ROUND:		/*		 * miRoundCap just needs these to be unequal.		 */		endPoint = center;		endPoint.x = endPoint.x + 100;		miRoundCap (pDraw, pGC, center, endPoint, corner, otherCorner, 0,			    -xOrg, -yOrg, xFtrans, yFtrans);		break;	default:	  break;	}}/* MIROUNDCAP -- a private helper function * Put Rounded cap on end. pCenter is the center of this end of the line * pEnd is the center of the other end of the line. pCorner is one of the * two corners at this end of the line.   * NOTE:  pOtherCorner must be counter-clockwise from pCorner. *//*ARGSUSED*/static void miRoundCap(GdkDrawable *pDraw, GdkGC *pGC, SppPointRec pCenter, SppPointRec pEnd, SppPointRec pCorner,		       SppPointRec pOtherCorner, int fLineEnd, int xOrg, int yOrg,		       double xFtrans, double yFtrans){    int		cpt;    double	width;    SppArcRec	arc;    SppPointPtr	pArcPts;    width = (GDK_GC_FBDATA(pGC)->values.line_width ? (double)GDK_GC_FBDATA(pGC)->values.line_width : (double)1);    arc.x = pCenter.x - width/2;    arc.y = pCenter.y - width/2;    arc.width = width;    arc.height = width;    arc.angle1 = -(miDatan2 (pCorner.y - pCenter.y, pCorner.x - pCenter.x));    if(PTISEQUAL(pCenter, pEnd))	arc.angle2 = - 180.0;    else {	arc.angle2 = -miDatan2 (pOtherCorner.y - pCenter.y, pOtherCorner.x - pCenter.x) - arc.angle1;	if (arc.angle2 < 0)	    arc.angle2 += 360.0;    }    pArcPts = (SppPointPtr) NULL;    if( (cpt = miGetArcPts(&arc, 0, &pArcPts)) )    {	/* by drawing with miFillSppPoly and setting the endpoints of the arc	 * to be the corners, we assure that the cap will meet up with the	 * rest of the line */	miFillSppPoly(pDraw, pGC, cpt, pArcPts, -xOrg, -yOrg, xFtrans, yFtrans);    }    g_free(pArcPts);}/* * To avoid inaccuracy at the cardinal points, use trig functions * which are exact for those angles */#ifndef M_PI#define M_PI	3.14159265358979323846#endif#ifndef M_PI_2#define M_PI_2	1.57079632679489661923#endif# define Dsin(d)	((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))# define Dcos(d)	((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))# define mod(a,b)	((a) >= 0 ? (a) % (b) : (b) - (-a) % (b))static doublemiDcos (double a){	int	i;	if (floor (a/90) == a/90) {		i = (int) (a/90.0);		switch (mod (i, 4)) {		case 0: return 1;		case 1: return 0;		case 2: return -1;		case 3: return 0;		}	}	return cos (a * M_PI / 180.0);}static doublemiDsin (double a){	int	i;	if (floor (a/90) == a/90) {		i = (int) (a/90.0);		switch (mod (i, 4)) {		case 0: return 0;		case 1: return 1;		case 2: return 0;		case 3: return -1;		}	}	return sin (a * M_PI / 180.0);}static doublemiDasin (double v){    if (v == 0)	return 0.0;    if (v == 1.0)	return 90.0;    if (v == -1.0)	return -90.0;    return asin(v) * (180.0 / M_PI);}static doublemiDatan2 (double dy, double dx){    if (dy == 0) {	if (dx >= 0)	    return 0.0;	return 180.0;    } else if (dx == 0) {	if (dy > 0)	    return 90.0;	return -90.0;    } else if (fabs (dy) == fabs (dx)) {	if (dy > 0) {	    if (dx > 0)		return 45.0;	    return 135.0;	} else {	    if (dx > 0)		return 315.0;	    return 225.0;	}    } else {	return atan2 (dy, dx) * (180.0 / M_PI);    }}/* MIGETARCPTS -- Converts an arc into a set of line segments -- a helper * routine for filled arc and line (round cap) code. * Returns the number of points in the arc.  Note that it takes a pointer * to a pointer to where it should put the points and an index (cpt). * This procedure allocates the space necessary to fit the arc points. * Sometimes it's convenient for those points to be at the end of an existing * array. (For example, if we want to leave a spare point to make sectors * instead of segments.)  So we pass in the g_malloc()ed chunk that contains the * array and an index saying where we should start stashing the points. * If there isn't an array already, we just pass in a null pointer and  * count on g_realloc() to handle the null pointer correctly. */static intmiGetArcPts(SppArcPtr parc, int cpt, SppPointPtr *ppPts)#if 0    SppArcPtr	parc;	/* points to an arc */    int		cpt;	/* number of points already in arc list */    SppPointPtr	*ppPts; /* pointer to pointer to arc-list -- modified */#endif{    double 	st,	/* Start Theta, start angle */                et,	/* End Theta, offset from start theta */		dt,	/* Delta Theta, angle to sweep ellipse */		cdt,	/* Cos Delta Theta, actually 2 cos(dt) */    		x0, y0,	/* the recurrence formula needs two points to start */		x1, y1,		x2, y2, /* this will be the new point generated */		xc, yc; /* the center point */    int		count, i;    SppPointPtr	poly;    GdkPoint last;		/* last point on integer boundaries */    /* The spec says that positive angles indicate counterclockwise motion.     * Given our coordinate system (with 0,0 in the upper left corner),      * the screen appears flipped in Y.  The easiest fix is to negate the     * angles given */        st = - parc->angle1;    et = - parc->angle2;    /* Try to get a delta theta that is within 1/2 pixel.  Then adjust it     * so that it divides evenly into the total.     * I'm just using cdt 'cause I'm lazy.     */    cdt = parc->width;    if (parc->height > cdt)	cdt = parc->height;    cdt /= 2.0;    if(cdt <= 0)	return 0;    if (cdt < 1.0)	cdt = 1.0;    dt = miDasin ( 1.0 / cdt ); /* minimum step necessary */    count = et/dt;    count = abs(count) + 1;    dt = et/count;	    count++;    cdt = 2 * miDcos(dt);

⌨️ 快捷键说明

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