コード例 #1
0
void
TkBezierScreenPoints(
    Tk_Canvas canvas,		/* Canvas in which curve is to be drawn. */
    double control[],		/* Array of coordinates for four control
				 * points: x0, y0, x1, y1, ... x3 y3. */
    int numSteps,		/* Number of curve points to generate. */
    register XPoint *xPointPtr)	/* Where to put new points. */
{
    int i;
    double u, u2, u3, t, t2, t3;

    for (i = 1; i <= numSteps; i++, xPointPtr++) {
	t = ((double) i)/((double) numSteps);
	t2 = t*t;
	t3 = t2*t;
	u = 1.0 - t;
	u2 = u*u;
	u3 = u2*u;
	Tk_CanvasDrawableCoords(canvas,
		(control[0]*u3 + 3.0 * (control[2]*t*u2 + control[4]*t2*u)
		    + control[6]*t3),
		(control[1]*u3 + 3.0 * (control[3]*t*u2 + control[5]*t2*u)
		    + control[7]*t3),
		&xPointPtr->x, &xPointPtr->y);
    }
}
コード例 #2
0
ファイル: tkCanvBLine.c プロジェクト: pip010/scirun4plus
static void
DisplayBLine(Tk_Canvas canvas, Tk_Item *itemPtr, Display *display, 
            Drawable drawable, int x, int y, int width, int height)
{
  register BLineItem *linePtr = (BLineItem *) itemPtr;
  XPoint staticPoints[MAX_STATIC_POINTS];
  XPoint *pointPtr;
  register XPoint *pPtr;
  register double *coordPtr;
  int i, numPoints;

  /*
   * Build up an array of points in screen coordinates.  Use a
   * static array unless the line has an enormous number of points;
   * in this case, dynamically allocate an array.  For smoothed lines,
   * generate the curve points on each redisplay.
   */

  numPoints = linePtr->numPoints;

  if (numPoints <= MAX_STATIC_POINTS) 
  {
    pointPtr = staticPoints;
  } 
  else 
  {
    pointPtr = (XPoint *) ckalloc((unsigned) (numPoints * sizeof(XPoint)));
  }

  for (i = 0, coordPtr = linePtr->coordPtr, pPtr = pointPtr;
    i < linePtr->numPoints;  i += 1, coordPtr += 2, pPtr++) 
  {
    Tk_CanvasDrawableCoords(canvas, coordPtr[0], coordPtr[1],
      &pPtr->x, &pPtr->y);
  }

  Tk_DrawBeveledLine(display, drawable, linePtr->border,
		       pointPtr, numPoints, linePtr->width,
		       linePtr->borderWidth, linePtr->relief);
    
  if (pointPtr != staticPoints) 
  {
    ckfree((char *) pointPtr);
  }
}
コード例 #3
0
ファイル: tkCanvImg.c プロジェクト: FreddieAkeroyd/TkTclTix
static void
DisplayImage(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    Tk_Item *itemPtr,		/* Item to be displayed. */
    Display *display,		/* Display on which to draw item. */
    Drawable drawable,		/* Pixmap or window in which to draw item. */
    int x, int y, int width, int height)
/* Describes region of canvas that must be
 * redisplayed (not used). */
{
    ImageItem *imgPtr = (ImageItem *) itemPtr;
    short drawableX, drawableY;
    Tk_Image image;
    Tk_State state = itemPtr->state;

    if (state == TK_STATE_NULL) {
        state = Canvas(canvas)->canvas_state;
    }

    image = imgPtr->image;
    if (Canvas(canvas)->currentItemPtr == itemPtr) {
        if (imgPtr->activeImage != NULL) {
            image = imgPtr->activeImage;
        }
    } else if (state == TK_STATE_DISABLED) {
        if (imgPtr->disabledImage != NULL) {
            image = imgPtr->disabledImage;
        }
    }

    if (image == NULL) {
        return;
    }

    /*
     * Translate the coordinates to those of the image, then redisplay it.
     */

    Tk_CanvasDrawableCoords(canvas, (double) x, (double) y,
                            &drawableX, &drawableY);
    Tk_RedrawImage(image, x - imgPtr->header.x1, y - imgPtr->header.y1,
                   width, height, drawable, drawableX, drawableY);
}
コード例 #4
0
ファイル: tkRectOval.c プロジェクト: AlexShiLucky/bitkeeper
static void
DisplayRectOval(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    Tk_Item *itemPtr,		/* Item to be displayed. */
    Display *display,		/* Display on which to draw item. */
    Drawable drawable,		/* Pixmap or window in which to draw item. */
    int x, int y, int width, int height)
				/* Describes region of canvas that must be
				 * redisplayed (not used). */
{
    RectOvalItem *rectOvalPtr = (RectOvalItem *) itemPtr;
    short x1, y1, x2, y2;
    Pixmap fillStipple;
    Tk_State state = itemPtr->state;

    /*
     * Compute the screen coordinates of the bounding box for the item. Make
     * sure that the bbox is at least one pixel large, since some X servers
     * will die if it isn't.
     */

    Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[0],rectOvalPtr->bbox[1],
	    &x1, &y1);
    Tk_CanvasDrawableCoords(canvas, rectOvalPtr->bbox[2],rectOvalPtr->bbox[3],
	    &x2, &y2);
    if (x2 <= x1) {
	x2 = x1+1;
    }
    if (y2 <= y1) {
	y2 = y1+1;
    }

    /*
     * Display filled part first (if wanted), then outline. If we're
     * stippling, then modify the stipple offset in the GC. Be sure to reset
     * the offset when done, since the GC is supposed to be read-only.
     */

    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }
    fillStipple = rectOvalPtr->fillStipple;
    if (Canvas(canvas)->currentItemPtr == (Tk_Item *) rectOvalPtr) {
	if (rectOvalPtr->activeFillStipple != None) {
	    fillStipple = rectOvalPtr->activeFillStipple;
	}
    } else if (state == TK_STATE_DISABLED) {
	if (rectOvalPtr->disabledFillStipple != None) {
	    fillStipple = rectOvalPtr->disabledFillStipple;
	}
    }

    if (rectOvalPtr->fillGC != None) {
	if (fillStipple != None) {
	    Tk_TSOffset *tsoffset;
	    int w = 0, h = 0;

	    tsoffset = &rectOvalPtr->tsoffset;
	    if (tsoffset) {
		int flags = tsoffset->flags;

		if (flags & (TK_OFFSET_CENTER|TK_OFFSET_MIDDLE)) {
		    Tk_SizeOfBitmap(display, fillStipple, &w, &h);
		    if (flags & TK_OFFSET_CENTER) {
			w /= 2;
		    } else {
			w = 0;
		    }
		    if (flags & TK_OFFSET_MIDDLE) {
			h /= 2;
		    } else {
			h = 0;
		    }
		}
		tsoffset->xoffset -= w;
		tsoffset->yoffset -= h;
	    }
	    Tk_CanvasSetOffset(canvas, rectOvalPtr->fillGC, tsoffset);
	    if (tsoffset) {
		tsoffset->xoffset += w;
		tsoffset->yoffset += h;
	    }
	}
	if (rectOvalPtr->header.typePtr == &tkRectangleType) {
	    XFillRectangle(display, drawable, rectOvalPtr->fillGC,
		    x1, y1, (unsigned int) (x2-x1), (unsigned int) (y2-y1));
	} else {
	    XFillArc(display, drawable, rectOvalPtr->fillGC,
		    x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1),
		    0, 360*64);
	}
	if (fillStipple != None) {
	    XSetTSOrigin(display, rectOvalPtr->fillGC, 0, 0);
	}
    }

    if (rectOvalPtr->outline.gc != None) {
	Tk_ChangeOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));
	if (rectOvalPtr->header.typePtr == &tkRectangleType) {
	    XDrawRectangle(display, drawable, rectOvalPtr->outline.gc,
		    x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1));
	} else {
	    XDrawArc(display, drawable, rectOvalPtr->outline.gc,
		    x1, y1, (unsigned) (x2-x1), (unsigned) (y2-y1), 0, 360*64);
	}
	Tk_ResetOutlineGC(canvas, itemPtr, &(rectOvalPtr->outline));
    }
}
コード例 #5
0
ファイル: tkCanvBmap.c プロジェクト: das/tcltk
static void
DisplayBitmap(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    Tk_Item *itemPtr,		/* Item to be displayed. */
    Display *display,		/* Display on which to draw item. */
    Drawable drawable,		/* Pixmap or window in which to draw item. */
    int x, int y, int width, int height)
				/* Describes region of canvas that must be
				 * redisplayed (not used). */
{
    BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
    int bmapX, bmapY, bmapWidth, bmapHeight;
    short drawableX, drawableY;
    Pixmap bitmap;
    Tk_State state = itemPtr->state;

    /*
     * If the area being displayed doesn't cover the whole bitmap, then only
     * redisplay the part of the bitmap that needs redisplay.
     */

    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }
    bitmap = bmapPtr->bitmap;
    if (Canvas(canvas)->currentItemPtr == itemPtr) {
	if (bmapPtr->activeBitmap!=None) {
	    bitmap = bmapPtr->activeBitmap;
	}
    } else if (state == TK_STATE_DISABLED) {
	if (bmapPtr->disabledBitmap!=None) {
	    bitmap = bmapPtr->disabledBitmap;
	}
    }

    if (bitmap != None) {
	if (x > bmapPtr->header.x1) {
	    bmapX = x - bmapPtr->header.x1;
	    bmapWidth = bmapPtr->header.x2 - x;
	} else {
	    bmapX = 0;
	    if ((x+width) < bmapPtr->header.x2) {
		bmapWidth = x + width - bmapPtr->header.x1;
	    } else {
		bmapWidth = bmapPtr->header.x2 - bmapPtr->header.x1;
	    }
	}
	if (y > bmapPtr->header.y1) {
	    bmapY = y - bmapPtr->header.y1;
	    bmapHeight = bmapPtr->header.y2 - y;
	} else {
	    bmapY = 0;
	    if ((y+height) < bmapPtr->header.y2) {
		bmapHeight = y + height - bmapPtr->header.y1;
	    } else {
		bmapHeight = bmapPtr->header.y2 - bmapPtr->header.y1;
	    }
	}
	Tk_CanvasDrawableCoords(canvas,
		(double) (bmapPtr->header.x1 + bmapX),
		(double) (bmapPtr->header.y1 + bmapY),
		&drawableX, &drawableY);

	/*
	 * Must modify the mask origin within the graphics context to line up
	 * with the bitmap's origin (in order to make bitmaps with
	 * "-background {}" work right).
	 */

	XSetClipOrigin(display, bmapPtr->gc, drawableX - bmapX,
		drawableY - bmapY);
	XCopyPlane(display, bitmap, drawable,
		bmapPtr->gc, bmapX, bmapY, (unsigned int) bmapWidth,
		(unsigned int) bmapHeight, drawableX, drawableY, 1);
	XSetClipOrigin(display, bmapPtr->gc, 0, 0);
    }
}
コード例 #6
0
int
TkMakeRawCurve(
    Tk_Canvas canvas,		/* Canvas in which curve is to be drawn. */
    double *pointPtr,		/* Array of input coordinates: x0, y0, x1, y1,
				 * etc.. */
    int numPoints,		/* Number of points at pointPtr. */
    int numSteps,		/* Number of steps to use for each curve
				 * segment (determines smoothness of
				 * curve). */
    XPoint xPoints[],		/* Array of XPoints to fill in (e.g. for
				 * display). NULL means don't fill in any
				 * XPoints. */
    double dblPoints[])		/* Array of points to fill in as doubles, in
				 * the form x0, y0, x1, y1, .... NULL means
				 * don't fill in anything in this form.
				 * Caller must make sure that this array has
				 * enough space. */
{
    int outputPoints, i;
    int numSegments = (numPoints+1)/3;
    double *segPtr;

    /*
     * The input describes a curve with s Bezier curve segments if there are
     * 3s+1, 3s, or 3s-1 input points. In the last two cases, 1 or 2 initial
     * points from the first curve segment are reused as defining points also
     * for the last curve segment. In the case of 3s input points, this will
     * automatically close the curve.
     */

    if (!pointPtr) {
	/*
	 * If pointPtr == NULL, this function returns an upper limit of the
	 * array size to store the coordinates. This can be used to allocate
	 * storage, before the actual coordinates are calculated.
	 */

	return 1 + numSegments * numSteps;
    }

    outputPoints = 0;
    if (xPoints != NULL) {
	Tk_CanvasDrawableCoords(canvas, pointPtr[0], pointPtr[1],
		&xPoints->x, &xPoints->y);
	xPoints += 1;
    }
    if (dblPoints != NULL) {
	dblPoints[0] = pointPtr[0];
	dblPoints[1] = pointPtr[1];
	dblPoints += 2;
    }
    outputPoints += 1;

    /*
     * The next loop handles all curve segments except one that overlaps the
     * end of the list of coordinates.
     */

    for (i=numPoints,segPtr=pointPtr ; i>=4 ; i-=3,segPtr+=6) {
	if (segPtr[0]==segPtr[2] && segPtr[1]==segPtr[3] &&
		segPtr[4]==segPtr[6] && segPtr[5]==segPtr[7]) {
	    /*
	     * The control points on this segment are equal to their
	     * neighbouring knots, so this segment is just a straight line. A
	     * single point is sufficient.
	     */

	    if (xPoints != NULL) {
		Tk_CanvasDrawableCoords(canvas, segPtr[6], segPtr[7],
			&xPoints->x, &xPoints->y);
		xPoints += 1;
	    }
	    if (dblPoints != NULL) {
		dblPoints[0] = segPtr[6];
		dblPoints[1] = segPtr[7];
		dblPoints += 2;
	    }
	    outputPoints += 1;
	} else {
	    /*
	     * This is a generic Bezier curve segment.
	     */

	    if (xPoints != NULL) {
		TkBezierScreenPoints(canvas, segPtr, numSteps, xPoints);
		xPoints += numSteps;
	    }
	    if (dblPoints != NULL) {
		TkBezierPoints(segPtr, numSteps, dblPoints);
		dblPoints += 2*numSteps;
	    }
	    outputPoints += numSteps;
	}
    }

    /*
     * If at this point i>1, then there is some point which has not yet been
     * used. Make another curve segment.
     */

    if (i > 1) {
	int j;
	double control[8];

	/*
	 * Copy the relevant coordinates to control[], so that it can be
	 * passed as a unit to e.g. TkBezierPoints.
	 */

	for (j=0; j<2*i; j++) {
	    control[j] = segPtr[j];
	}
	for (; j<8; j++) {
	    control[j] = pointPtr[j-2*i];
	}

	/*
	 * Then we just do the same things as above.
	 */

	if (control[0]==control[2] && control[1]==control[3] &&
		control[4]==control[6] && control[5]==control[7]) {
	    /*
	     * The control points on this segment are equal to their
	     * neighbouring knots, so this segment is just a straight line. A
	     * single point is sufficient.
	     */

	    if (xPoints != NULL) {
		Tk_CanvasDrawableCoords(canvas, control[6], control[7],
			&xPoints->x, &xPoints->y);
		xPoints += 1;
	    }
	    if (dblPoints != NULL) {
		dblPoints[0] = control[6];
		dblPoints[1] = control[7];
		dblPoints += 2;
	    }
	    outputPoints += 1;
	} else {
	    /*
	     * This is a generic Bezier curve segment.
	     */

	    if (xPoints != NULL) {
		TkBezierScreenPoints(canvas, control, numSteps, xPoints);
		xPoints += numSteps;
	    }
	    if (dblPoints != NULL) {
		TkBezierPoints(control, numSteps, dblPoints);
		dblPoints += 2*numSteps;
	    }
	    outputPoints += numSteps;
	}
    }

    return outputPoints;
}
コード例 #7
0
int
TkMakeBezierCurve(
    Tk_Canvas canvas,		/* Canvas in which curve is to be drawn. */
    double *pointPtr,		/* Array of input coordinates: x0, y0, x1, y1,
				 * etc.. */
    int numPoints,		/* Number of points at pointPtr. */
    int numSteps,		/* Number of steps to use for each spline
				 * segments (determines smoothness of
				 * curve). */
    XPoint xPoints[],		/* Array of XPoints to fill in (e.g. for
				 * display). NULL means don't fill in any
				 * XPoints. */
    double dblPoints[])		/* Array of points to fill in as doubles, in
				 * the form x0, y0, x1, y1, .... NULL means
				 * don't fill in anything in this form. Caller
				 * must make sure that this array has enough
				 * space. */
{
    int closed, outputPoints, i;
    int numCoords = numPoints*2;
    double control[8];

    /*
     * If the curve is a closed one then generate a special spline that spans
     * the last points and the first ones. Otherwise just put the first point
     * into the output.
     */

    if (!pointPtr) {
	/*
	 * Of pointPtr == NULL, this function returns an upper limit of the
	 * array size to store the coordinates. This can be used to allocate
	 * storage, before the actual coordinates are calculated.
	 */

	return 1 + numPoints * numSteps;
    }

    outputPoints = 0;
    if ((pointPtr[0] == pointPtr[numCoords-2])
	    && (pointPtr[1] == pointPtr[numCoords-1])) {
	closed = 1;
	control[0] = 0.5*pointPtr[numCoords-4] + 0.5*pointPtr[0];
	control[1] = 0.5*pointPtr[numCoords-3] + 0.5*pointPtr[1];
	control[2] = 0.167*pointPtr[numCoords-4] + 0.833*pointPtr[0];
	control[3] = 0.167*pointPtr[numCoords-3] + 0.833*pointPtr[1];
	control[4] = 0.833*pointPtr[0] + 0.167*pointPtr[2];
	control[5] = 0.833*pointPtr[1] + 0.167*pointPtr[3];
	control[6] = 0.5*pointPtr[0] + 0.5*pointPtr[2];
	control[7] = 0.5*pointPtr[1] + 0.5*pointPtr[3];
	if (xPoints != NULL) {
	    Tk_CanvasDrawableCoords(canvas, control[0], control[1],
		    &xPoints->x, &xPoints->y);
	    TkBezierScreenPoints(canvas, control, numSteps, xPoints+1);
	    xPoints += numSteps+1;
	}
	if (dblPoints != NULL) {
	    dblPoints[0] = control[0];
	    dblPoints[1] = control[1];
	    TkBezierPoints(control, numSteps, dblPoints+2);
	    dblPoints += 2*(numSteps+1);
	}
	outputPoints += numSteps+1;
    } else {
	closed = 0;
	if (xPoints != NULL) {
	    Tk_CanvasDrawableCoords(canvas, pointPtr[0], pointPtr[1],
		    &xPoints->x, &xPoints->y);
	    xPoints += 1;
	}
	if (dblPoints != NULL) {
	    dblPoints[0] = pointPtr[0];
	    dblPoints[1] = pointPtr[1];
	    dblPoints += 2;
	}
	outputPoints += 1;
    }

    for (i = 2; i < numPoints; i++, pointPtr += 2) {
	/*
	 * Set up the first two control points. This is done differently for
	 * the first spline of an open curve than for other cases.
	 */

	if ((i == 2) && !closed) {
	    control[0] = pointPtr[0];
	    control[1] = pointPtr[1];
	    control[2] = 0.333*pointPtr[0] + 0.667*pointPtr[2];
	    control[3] = 0.333*pointPtr[1] + 0.667*pointPtr[3];
	} else {
	    control[0] = 0.5*pointPtr[0] + 0.5*pointPtr[2];
	    control[1] = 0.5*pointPtr[1] + 0.5*pointPtr[3];
	    control[2] = 0.167*pointPtr[0] + 0.833*pointPtr[2];
	    control[3] = 0.167*pointPtr[1] + 0.833*pointPtr[3];
	}

	/*
	 * Set up the last two control points. This is done differently for
	 * the last spline of an open curve than for other cases.
	 */

	if ((i == (numPoints-1)) && !closed) {
	    control[4] = .667*pointPtr[2] + .333*pointPtr[4];
	    control[5] = .667*pointPtr[3] + .333*pointPtr[5];
	    control[6] = pointPtr[4];
	    control[7] = pointPtr[5];
	} else {
	    control[4] = .833*pointPtr[2] + .167*pointPtr[4];
	    control[5] = .833*pointPtr[3] + .167*pointPtr[5];
	    control[6] = 0.5*pointPtr[2] + 0.5*pointPtr[4];
	    control[7] = 0.5*pointPtr[3] + 0.5*pointPtr[5];
	}

	/*
	 * If the first two points coincide, or if the last two points
	 * coincide, then generate a single straight-line segment by
	 * outputting the last control point.
	 */

	if (((pointPtr[0] == pointPtr[2]) && (pointPtr[1] == pointPtr[3]))
		|| ((pointPtr[2] == pointPtr[4])
		&& (pointPtr[3] == pointPtr[5]))) {
	    if (xPoints != NULL) {
		Tk_CanvasDrawableCoords(canvas, control[6], control[7],
			&xPoints[0].x, &xPoints[0].y);
		xPoints++;
	    }
	    if (dblPoints != NULL) {
		dblPoints[0] = control[6];
		dblPoints[1] = control[7];
		dblPoints += 2;
	    }
	    outputPoints += 1;
	    continue;
	}

	/*
	 * Generate a Bezier spline using the control points.
	 */


	if (xPoints != NULL) {
	    TkBezierScreenPoints(canvas, control, numSteps, xPoints);
	    xPoints += numSteps;
	}
	if (dblPoints != NULL) {
	    TkBezierPoints(control, numSteps, dblPoints);
	    dblPoints += 2*numSteps;
	}
	outputPoints += numSteps;
    }
    return outputPoints;
}
コード例 #8
0
ファイル: tkCanvText.c プロジェクト: tcltk/tk
static void
DisplayCanvText(
    Tk_Canvas canvas,		/* Canvas that contains item. */
    Tk_Item *itemPtr,		/* Item to be displayed. */
    Display *display,		/* Display on which to draw item. */
    Drawable drawable,		/* Pixmap or window in which to draw item. */
    int x, int y, int width, int height)
				/* Describes region of canvas that must be
				 * redisplayed (not used). */
{
    TextItem *textPtr;
    Tk_CanvasTextInfo *textInfoPtr;
    int selFirstChar, selLastChar;
    short drawableX, drawableY;
    Pixmap stipple;
    Tk_State state = itemPtr->state;

    textPtr = (TextItem *) itemPtr;
    textInfoPtr = textPtr->textInfoPtr;

    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }
    stipple = textPtr->stipple;
    if (Canvas(canvas)->currentItemPtr == itemPtr) {
	if (textPtr->activeStipple != None) {
	    stipple = textPtr->activeStipple;
	}
    } else if (state == TK_STATE_DISABLED) {
	if (textPtr->disabledStipple != None) {
	    stipple = textPtr->disabledStipple;
	}
    }

    if (textPtr->gc == NULL) {
	return;
    }

    /*
     * If we're stippling, then modify the stipple offset in the GC. Be sure
     * to reset the offset when done, since the GC is supposed to be
     * read-only.
     */

    if (stipple != None) {
	Tk_CanvasSetOffset(canvas, textPtr->gc, &textPtr->tsoffset);
    }

    selFirstChar = -1;
    selLastChar = 0;		/* lint. */
    Tk_CanvasDrawableCoords(canvas, textPtr->drawOrigin[0],
	    textPtr->drawOrigin[1], &drawableX, &drawableY);

    if (textInfoPtr->selItemPtr == itemPtr) {
	selFirstChar = textInfoPtr->selectFirst;
	selLastChar = textInfoPtr->selectLast;
	if (selLastChar > textPtr->numChars) {
	    selLastChar = textPtr->numChars - 1;
	}
	if ((selFirstChar >= 0) && (selFirstChar <= selLastChar)) {
	    int xFirst, yFirst, hFirst;
	    int xLast, yLast, wLast;

	    /*
	     * Draw a special background under the selection.
	     */

	    Tk_CharBbox(textPtr->textLayout, selFirstChar, &xFirst, &yFirst,
		    NULL, &hFirst);
	    Tk_CharBbox(textPtr->textLayout, selLastChar, &xLast, &yLast,
		    &wLast, NULL);

	    /*
	     * If the selection spans the end of this line, then display
	     * selection background all the way to the end of the line.
	     * However, for the last line we only want to display up to the
	     * last character, not the end of the line.
	     */

	    x = xFirst;
	    height = hFirst;
	    for (y = yFirst ; y <= yLast; y += height) {
		int dx1, dy1, dx2, dy2;
		double s = textPtr->sine, c = textPtr->cosine;
		XPoint points[4];

		if (y == yLast) {
		    width = xLast + wLast - x;
		} else {
		    width = textPtr->actualWidth - x;
		}
		dx1 = x - textInfoPtr->selBorderWidth;
		dy1 = y;
		dx2 = width + 2 * textInfoPtr->selBorderWidth;
		dy2 = height;
		points[0].x = (short)(drawableX + dx1*c + dy1*s);
		points[0].y = (short)(drawableY + dy1*c - dx1*s);
		points[1].x = (short)(drawableX + (dx1+dx2)*c + dy1*s);
		points[1].y = (short)(drawableY + dy1*c - (dx1+dx2)*s);
		points[2].x = (short)(drawableX + (dx1+dx2)*c + (dy1+dy2)*s);
		points[2].y = (short)(drawableY + (dy1+dy2)*c - (dx1+dx2)*s);
		points[3].x = (short)(drawableX + dx1*c + (dy1+dy2)*s);
		points[3].y = (short)(drawableY + (dy1+dy2)*c - dx1*s);
		Tk_Fill3DPolygon(Tk_CanvasTkwin(canvas), drawable,
			textInfoPtr->selBorder, points, 4,
			textInfoPtr->selBorderWidth, TK_RELIEF_RAISED);
		x = 0;
	    }
	}
    }

    /*
     * If the insertion point should be displayed, then draw a special
     * background for the cursor before drawing the text. Note: if we're the
     * cursor item but the cursor is turned off, then redraw background over
     * the area of the cursor. This guarantees that the selection won't make
     * the cursor invisible on mono displays, where both are drawn in the same
     * color.
     */

    if ((textInfoPtr->focusItemPtr == itemPtr) && (textInfoPtr->gotFocus)) {
	if (Tk_CharBbox(textPtr->textLayout, textPtr->insertPos,
		&x, &y, NULL, &height)) {
	    int dx1, dy1, dx2, dy2;
	    double s = textPtr->sine, c = textPtr->cosine;
	    XPoint points[4];

	    dx1 = x - (textInfoPtr->insertWidth / 2);
	    dy1 = y;
	    dx2 = textInfoPtr->insertWidth;
	    dy2 = height;
	    points[0].x = (short)(drawableX + dx1*c + dy1*s);
	    points[0].y = (short)(drawableY + dy1*c - dx1*s);
	    points[1].x = (short)(drawableX + (dx1+dx2)*c + dy1*s);
	    points[1].y = (short)(drawableY + dy1*c - (dx1+dx2)*s);
	    points[2].x = (short)(drawableX + (dx1+dx2)*c + (dy1+dy2)*s);
	    points[2].y = (short)(drawableY + (dy1+dy2)*c - (dx1+dx2)*s);
	    points[3].x = (short)(drawableX + dx1*c + (dy1+dy2)*s);
	    points[3].y = (short)(drawableY + (dy1+dy2)*c - dx1*s);

	    Tk_SetCaretPos(Tk_CanvasTkwin(canvas), points[0].x, points[0].y,
		    height);
	    if (textInfoPtr->cursorOn) {
		Tk_Fill3DPolygon(Tk_CanvasTkwin(canvas), drawable,
			textInfoPtr->insertBorder, points, 4,
			textInfoPtr->insertBorderWidth, TK_RELIEF_RAISED);
	    } else if (textPtr->cursorOffGC != NULL) {
		/*
		 * Redraw the background over the area of the cursor, even
		 * though the cursor is turned off. This guarantees that the
		 * selection won't make the cursor invisible on mono displays,
		 * where both may be drawn in the same color.
		 */

		XFillPolygon(display, drawable, textPtr->cursorOffGC,
			points, 4, Convex, CoordModeOrigin);
	    }
	}
    }

    /*
     * If there is no selected text or the selected text foreground is the
     * same as the regular text foreground, then draw one text string. If
     * there is selected text and the foregrounds differ, draw the regular
     * text up to the selection, draw the selection, then draw the rest of the
     * regular text. Drawing the regular text and then the selected text over
     * it would causes problems with anti-aliased text because the two
     * anti-aliasing colors would blend together.
     */

    if ((selFirstChar >= 0) && (textPtr->selTextGC != textPtr->gc)) {
	TkDrawAngledTextLayout(display, drawable, textPtr->gc,
		textPtr->textLayout, drawableX, drawableY, textPtr->angle,
		0, selFirstChar);
	TkDrawAngledTextLayout(display, drawable, textPtr->selTextGC,
		textPtr->textLayout, drawableX, drawableY, textPtr->angle,
		selFirstChar, selLastChar + 1);
	TkDrawAngledTextLayout(display, drawable, textPtr->gc,
		textPtr->textLayout, drawableX, drawableY, textPtr->angle,
		selLastChar + 1, -1);
    } else {
	TkDrawAngledTextLayout(display, drawable, textPtr->gc,
		textPtr->textLayout, drawableX, drawableY, textPtr->angle,
		0, -1);
    }
    TkUnderlineAngledTextLayout(display, drawable, textPtr->gc,
	    textPtr->textLayout, drawableX, drawableY, textPtr->angle,
	    textPtr->underline);

    if (stipple != None) {
	XSetTSOrigin(display, textPtr->gc, 0, 0);
    }
}