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

📄 tk3d.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 2 页
字号:
 */voidTk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,	borderWidth, leftRelief)    Tk_Window tkwin;		/* Window for which border was allocated. */    Drawable drawable;		/* X window or pixmap in which to draw. */    Tk_3DBorder border;		/* Token for border to draw. */    XPoint *pointPtr;		/* Array of points describing				 * polygon.  All points must be				 * absolute (CoordModeOrigin). */    int numPoints;		/* Number of points at *pointPtr. */    int borderWidth;		/* Width of border, measured in				 * pixels to the left of the polygon's				 * trajectory.   May be negative. */    int leftRelief;		/* TK_RELIEF_RAISED or				 * TK_RELIEF_SUNKEN: indicates how				 * stuff to left of trajectory looks				 * relative to stuff on right. */{    XPoint poly[4], b1, b2, newB1, newB2;    XPoint perp, c, shift1, shift2;	/* Used for handling parallel lines. */    register XPoint *p1Ptr, *p2Ptr;    TkBorder *borderPtr = (TkBorder *) border;    GC gc;    int i, lightOnLeft, dx, dy, parallel, pointsSeen;    Display *display = Tk_Display(tkwin);    if (borderPtr->lightGC == None) {	TkpGetShadows(borderPtr, tkwin);    }    /*     * Handle grooves and ridges with recursive calls.     */    if ((leftRelief == TK_RELIEF_GROOVE) || (leftRelief == TK_RELIEF_RIDGE)) {	int halfWidth;	halfWidth = borderWidth/2;	Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,		halfWidth, (leftRelief == TK_RELIEF_GROOVE) ? TK_RELIEF_RAISED		: TK_RELIEF_SUNKEN);	Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,		-halfWidth, (leftRelief == TK_RELIEF_GROOVE) ? TK_RELIEF_SUNKEN		: TK_RELIEF_RAISED);	return;    }    /*     * If the polygon is already closed, drop the last point from it     * (we'll close it automatically).     */    p1Ptr = &pointPtr[numPoints-1];    p2Ptr = &pointPtr[0];    if ((p1Ptr->x == p2Ptr->x) && (p1Ptr->y == p2Ptr->y)) {	numPoints--;    }    /*     * The loop below is executed once for each vertex in the polgon.     * At the beginning of each iteration things look like this:     *     *          poly[1]       /     *             *        /     *             |      /     *             b1   * poly[0] (pointPtr[i-1])     *             |    |     *             |    |     *             |    |     *             |    |     *             |    |     *             |    | *p1Ptr            *p2Ptr     *             b2   *--------------------*     *             |     *             |     *             x-------------------------     *     * The job of this iteration is to do the following:     * (a) Compute x (the border corner corresponding to     *     pointPtr[i]) and put it in poly[2].  As part of     *	   this, compute a new b1 and b2 value for the next     *	   side of the polygon.     * (b) Put pointPtr[i] into poly[3].     * (c) Draw the polygon given by poly[0..3].     * (d) Advance poly[0], poly[1], b1, and b2 for the     *     next side of the polygon.     */    /*     * The above situation doesn't first come into existence until     * two points have been processed;  the first two points are     * used to "prime the pump", so some parts of the processing     * are ommitted for these points.  The variable "pointsSeen"     * keeps track of the priming process;  it has to be separate     * from i in order to be able to ignore duplicate points in the     * polygon.     */    pointsSeen = 0;    for (i = -2, p1Ptr = &pointPtr[numPoints-2], p2Ptr = p1Ptr+1;	    i < numPoints; i++, p1Ptr = p2Ptr, p2Ptr++) {	if ((i == -1) || (i == numPoints-1)) {	    p2Ptr = pointPtr;	}	if ((p2Ptr->x == p1Ptr->x) && (p2Ptr->y == p1Ptr->y)) {	    /*	     * Ignore duplicate points (they'd cause core dumps in	     * ShiftLine calls below).	     */	    continue;	}	ShiftLine(p1Ptr, p2Ptr, borderWidth, &newB1);	newB2.x = newB1.x + (p2Ptr->x - p1Ptr->x);	newB2.y = newB1.y + (p2Ptr->y - p1Ptr->y);	poly[3] = *p1Ptr;	parallel = 0;	if (pointsSeen >= 1) {	    parallel = Intersect(&newB1, &newB2, &b1, &b2, &poly[2]);	    /*	     * If two consecutive segments of the polygon are parallel,	     * then things get more complex.  Consider the following	     * diagram:	     *	     * poly[1]	     *    *----b1-----------b2------a	     *                                \	     *                                  \	     *         *---------*----------*    b	     *        poly[0]  *p2Ptr   *p1Ptr  /	     *                                /	     *              --*--------*----c	     *              newB1    newB2	     *	     * Instead of using x and *p1Ptr for poly[2] and poly[3], as	     * in the original diagram, use a and b as above.  Then instead	     * of using x and *p1Ptr for the new poly[0] and poly[1], use	     * b and c as above.	     *	     * Do the computation in three stages:	     * 1. Compute a point "perp" such that the line p1Ptr-perp	     *    is perpendicular to p1Ptr-p2Ptr.	     * 2. Compute the points a and c by intersecting the lines	     *    b1-b2 and newB1-newB2 with p1Ptr-perp.	     * 3. Compute b by shifting p1Ptr-perp to the right and	     *    intersecting it with p1Ptr-p2Ptr.	     */	    if (parallel) {		perp.x = p1Ptr->x + (p2Ptr->y - p1Ptr->y);		perp.y = p1Ptr->y - (p2Ptr->x - p1Ptr->x);		(void) Intersect(p1Ptr, &perp, &b1, &b2, &poly[2]);		(void) Intersect(p1Ptr, &perp, &newB1, &newB2, &c);		ShiftLine(p1Ptr, &perp, borderWidth, &shift1);		shift2.x = shift1.x + (perp.x - p1Ptr->x);		shift2.y = shift1.y + (perp.y - p1Ptr->y);		(void) Intersect(p1Ptr, p2Ptr, &shift1, &shift2, &poly[3]);	    }	}	if (pointsSeen >= 2) {	    dx = poly[3].x - poly[0].x;	    dy = poly[3].y - poly[0].y;	    if (dx > 0) {		lightOnLeft = (dy <= dx);	    } else {		lightOnLeft = (dy < dx);	    }	    if (lightOnLeft ^ (leftRelief == TK_RELIEF_RAISED)) {		gc = borderPtr->lightGC;	    } else {		gc = borderPtr->darkGC;	    }	    XFillPolygon(display, drawable, gc, poly, 4, Convex,		    CoordModeOrigin);	}	b1.x = newB1.x;	b1.y = newB1.y;	b2.x = newB2.x;	b2.y = newB2.y;	poly[0].x = poly[3].x;	poly[0].y = poly[3].y;	if (parallel) {	    poly[1].x = c.x;	    poly[1].y = c.y;	} else if (pointsSeen >= 1) {	    poly[1].x = poly[2].x;	    poly[1].y = poly[2].y;	}	pointsSeen++;    }}/* *---------------------------------------------------------------------- * * Tk_Fill3DRectangle -- * *	Fill a rectangular area, supplying a 3D border if desired. * * Results: *	None. * * Side effects: *	Information gets drawn on the screen. * *---------------------------------------------------------------------- */voidTk_Fill3DRectangle(tkwin, drawable, border, x, y, width,	height, borderWidth, relief)    Tk_Window tkwin;		/* Window for which border was allocated. */    Drawable drawable;		/* X window or pixmap in which to draw. */    Tk_3DBorder border;		/* Token for border to draw. */    int x, y, width, height;	/* Outside area of rectangular region. */    int borderWidth;		/* Desired width for border, in				 * pixels. Border will be *inside* region. */    int relief;			/* Indicates 3D effect: TK_RELIEF_FLAT,				 * TK_RELIEF_RAISED, or TK_RELIEF_SUNKEN. */{    register TkBorder *borderPtr = (TkBorder *) border;    int doubleBorder;    /*     * This code is slightly tricky because it only draws the background     * in areas not covered by the 3D border. This avoids flashing     * effects on the screen for the border region.     */      if (relief == TK_RELIEF_FLAT) {	borderWidth = 0;    }    doubleBorder = 2*borderWidth;    if ((width > doubleBorder) && (height > doubleBorder)) {	XFillRectangle(Tk_Display(tkwin), drawable, borderPtr->bgGC,		x + borderWidth, y + borderWidth,		(unsigned int) (width - doubleBorder),		(unsigned int) (height - doubleBorder));    }    if (borderWidth) {	Tk_Draw3DRectangle(tkwin, drawable, border, x, y, width,		height, borderWidth, relief);    }}/* *---------------------------------------------------------------------- * * Tk_Fill3DPolygon -- * *	Fill a polygonal area, supplying a 3D border if desired. * * Results: *	None. * * Side effects: *	Information gets drawn on the screen. * *---------------------------------------------------------------------- */voidTk_Fill3DPolygon(tkwin, drawable, border, pointPtr, numPoints,	borderWidth, leftRelief)    Tk_Window tkwin;		/* Window for which border was allocated. */    Drawable drawable;		/* X window or pixmap in which to draw. */    Tk_3DBorder border;		/* Token for border to draw. */    XPoint *pointPtr;		/* Array of points describing				 * polygon.  All points must be				 * absolute (CoordModeOrigin). */    int numPoints;		/* Number of points at *pointPtr. */    int borderWidth;		/* Width of border, measured in				 * pixels to the left of the polygon's				 * trajectory.   May be negative. */    int leftRelief;			/* Indicates 3D effect of left side of				 * trajectory relative to right:				 * TK_RELIEF_FLAT, TK_RELIEF_RAISED,				 * or TK_RELIEF_SUNKEN. */{    register TkBorder *borderPtr = (TkBorder *) border;    XFillPolygon(Tk_Display(tkwin), drawable, borderPtr->bgGC,	    pointPtr, numPoints, Complex, CoordModeOrigin);    if (leftRelief != TK_RELIEF_FLAT) {	Tk_Draw3DPolygon(tkwin, drawable, border, pointPtr, numPoints,		borderWidth, leftRelief);    }}/* *-------------------------------------------------------------- * * BorderInit -- * *	Initialize the structures used for border management. * * Results: *	None. * * Side effects: *	Read the code. * *------------------------------------------------------------- */static voidBorderInit(){    initialized = 1;    Tcl_InitHashTable(&borderTable, sizeof(BorderKey)/sizeof(int));}/* *-------------------------------------------------------------- * * ShiftLine -- * *	Given two points on a line, compute a point on a *	new line that is parallel to the given line and *	a given distance away from it. * * Results: *	None. * * Side effects: *	None. * *-------------------------------------------------------------- */static voidShiftLine(p1Ptr, p2Ptr, distance, p3Ptr)    XPoint *p1Ptr;		/* First point on line. */    XPoint *p2Ptr;		/* Second point on line. */    int distance;		/* New line is to be this many				 * units to the left of original				 * line, when looking from p1 to				 * p2.  May be negative. */    XPoint *p3Ptr;		/* Store coords of point on new				 * line here. */{    int dx, dy, dxNeg, dyNeg;    /*     * The table below is used for a quick approximation in     * computing the new point.  An index into the table     * is 128 times the slope of the original line (the slope     * must always be between 0 and 1).  The value of the table     * entry is 128 times the amount to displace the new line     * in y for each unit of perpendicular distance.  In other     * words, the table maps from the tangent of an angle to     * the inverse of its cosine.  If the slope of the original     * line is greater than 1, then the displacement is done in     * x rather than in y.     */    static int shiftTable[129];    /*     * Initialize the table if this is the first time it is     * used.     */    if (shiftTable[0] == 0) {	int i;	double tangent, cosine;	for (i = 0; i <= 128; i++) {	    tangent = i/128.0;	    cosine = 128/cos(atan(tangent)) + .5;	    shiftTable[i] = (int) cosine;	}    }    *p3Ptr = *p1Ptr;    dx = p2Ptr->x - p1Ptr->x;    dy = p2Ptr->y - p1Ptr->y;    if (dy < 0) {	dyNeg = 1;	dy = -dy;    } else {	dyNeg = 0;    }    if (dx < 0) {	dxNeg = 1;	dx = -dx;    } else {	dxNeg = 0;    }    if (dy <= dx) {	dy = ((distance * shiftTable[(dy<<7)/dx]) + 64) >> 7;	if (!dxNeg) {	    dy = -dy;	}	p3Ptr->y += dy;    } else {	dx = ((distance * shiftTable[(dx<<7)/dy]) + 64) >> 7;	if (dyNeg) {	    dx = -dx;	}	p3Ptr->x += dx;    }}/* *-------------------------------------------------------------- * * Intersect -- * *	Find the intersection point between two lines. * * Results: *	Under normal conditions 0 is returned and the point *	at *iPtr is filled in with the intersection between *	the two lines.  If the two lines are parallel, then *	-1 is returned and *iPtr isn't modified. * * Side effects: *	None. * *-------------------------------------------------------------- */static intIntersect(a1Ptr, a2Ptr, b1Ptr, b2Ptr, iPtr)    XPoint *a1Ptr;		/* First point of first line. */    XPoint *a2Ptr;		/* Second point of first line. */    XPoint *b1Ptr;		/* First point of second line. */    XPoint *b2Ptr;		/* Second point of second line. */    XPoint *iPtr;		/* Filled in with intersection point. */{    int dxadyb, dxbdya, dxadxb, dyadyb, p, q;    /*     * The code below is just a straightforward manipulation of two     * equations of the form y = (x-x1)*(y2-y1)/(x2-x1) + y1 to solve     * for the x-coordinate of intersection, then the y-coordinate.     */    dxadyb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->y - b1Ptr->y);    dxbdya = (b2Ptr->x - b1Ptr->x)*(a2Ptr->y - a1Ptr->y);    dxadxb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->x - b1Ptr->x);    dyadyb = (a2Ptr->y - a1Ptr->y)*(b2Ptr->y - b1Ptr->y);    if (dxadyb == dxbdya) {	return -1;    }    p = (a1Ptr->x*dxbdya - b1Ptr->x*dxadyb + (b1Ptr->y - a1Ptr->y)*dxadxb);    q = dxbdya - dxadyb;    if (q < 0) {	p = -p;	q = -q;    }    if (p < 0) {	iPtr->x = - ((-p + q/2)/q);    } else {	iPtr->x = (p + q/2)/q;    }    p = (a1Ptr->y*dxadyb - b1Ptr->y*dxbdya + (b1Ptr->x - a1Ptr->x)*dyadyb);    q = dxadyb - dxbdya;    if (q < 0) {	p = -p;	q = -q;    }    if (p < 0) {	iPtr->y = - ((-p + q/2)/q);    } else {	iPtr->y = (p + q/2)/q;    }    return 0;}

⌨️ 快捷键说明

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