summaryrefslogtreecommitdiffstats
path: root/carbon/tkMacOSXDraw.c
diff options
context:
space:
mode:
Diffstat (limited to 'carbon/tkMacOSXDraw.c')
-rw-r--r--carbon/tkMacOSXDraw.c2118
1 files changed, 2118 insertions, 0 deletions
diff --git a/carbon/tkMacOSXDraw.c b/carbon/tkMacOSXDraw.c
new file mode 100644
index 0000000..e028e45
--- /dev/null
+++ b/carbon/tkMacOSXDraw.c
@@ -0,0 +1,2118 @@
+/*
+ * tkMacOSXDraw.c --
+ *
+ * This file contains functions that perform drawing to
+ * Xlib windows. Most of the functions simple emulate
+ * Xlib functions.
+ *
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright 2001, Apple Computer, Inc.
+ * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "tkMacOSXPrivate.h"
+#include "tkMacOSXDebug.h"
+#include "xbytes.h"
+
+/*
+#ifdef TK_MAC_DEBUG
+#define TK_MAC_DEBUG_DRAWING
+#endif
+*/
+
+#define radians(d) ((d) * (M_PI/180.0))
+
+/*
+ * Non-antialiased CG drawing looks better and more like X11 drawing when using
+ * very fine lines, so decrease all linewidths by the following constant.
+ */
+#define NON_AA_CG_OFFSET .999
+
+/*
+ * Temporary region that can be reused.
+ */
+
+RgnHandle tkMacOSXtmpQdRgn = NULL;
+
+int tkMacOSXUseCGDrawing = 1;
+
+int tkPictureIsOpen;
+
+static PixPatHandle penPat = NULL, tmpPixPat = NULL;
+
+static int cgAntiAliasLimit = 0;
+#define notAA(w) ((w) < cgAntiAliasLimit)
+
+static int useThemedToplevel = 0;
+static int useThemedFrame = 0;
+
+/*
+ * Prototypes for functions used only in this file.
+ */
+
+static void ClipToGC(Drawable d, GC gc, HIShapeRef *clipRgnPtr);
+static void NoQDClip(CGrafPtr port);
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXInitCGDrawing --
+ *
+ * Initializes link vars that control CG drawing.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+MODULE_SCOPE int
+TkMacOSXInitCGDrawing(
+ Tcl_Interp *interp,
+ int enable,
+ int limit)
+{
+ static Boolean initialized = FALSE;
+
+ if (!initialized) {
+ initialized = TRUE;
+
+ if (Tcl_CreateNamespace(interp, "::tk::mac", NULL, NULL) == NULL) {
+ Tcl_ResetResult(interp);
+ }
+ if (Tcl_LinkVar(interp, "::tk::mac::useCGDrawing",
+ (char *) &tkMacOSXUseCGDrawing, TCL_LINK_BOOLEAN) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+ tkMacOSXUseCGDrawing = enable;
+
+ if (Tcl_LinkVar(interp, "::tk::mac::CGAntialiasLimit",
+ (char *) &cgAntiAliasLimit, TCL_LINK_INT) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+ cgAntiAliasLimit = limit;
+
+ /*
+ * Piggy-back the themed drawing var init here.
+ */
+
+ if (Tcl_LinkVar(interp, "::tk::mac::useThemedToplevel",
+ (char *) &useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+ if (Tcl_LinkVar(interp, "::tk::mac::useThemedFrame",
+ (char *) &useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+
+ if (tkMacOSXtmpQdRgn == NULL) {
+ tkMacOSXtmpQdRgn = NewRgn();
+ }
+ }
+#ifdef TK_MAC_DEBUG_DRAWING
+ TkMacOSXInitNamedDebugSymbol(QD, void, QD_DebugPrint, char*);
+ if (QD_DebugPrint) {
+ ; /* gdb: b *QD_DebugPrint */
+ }
+#endif /* TK_MAC_DEBUG_WINDOWS */
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XCopyArea --
+ *
+ * Copies data from one drawable to another using block transfer
+ * routines.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Data is moved from a window or bitmap to a second window or
+ * bitmap.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XCopyArea(
+ Display *display, /* Display. */
+ Drawable src, /* Source drawable. */
+ Drawable dst, /* Destination drawable. */
+ GC gc, /* GC to use. */
+ int src_x, /* X & Y, width & height */
+ int src_y, /* define the source rectangle */
+ unsigned int width, /* that will be copied. */
+ unsigned int height,
+ int dest_x, /* Dest X & Y on dest rect. */
+ int dest_y)
+{
+ TkMacOSXDrawingContext dc;
+ MacDrawable *srcDraw = (MacDrawable *) src, *dstDraw = (MacDrawable *) dst;
+
+ display->request++;
+ if (!width || !height) {
+ /* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */
+ return;
+ }
+ {
+ CGrafPtr srcPort;
+
+ srcPort = TkMacOSXGetDrawablePort(src);
+ if (srcPort) {
+ Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect;
+ const BitMap *srcBit, *dstBit;
+ RGBColor black = {0, 0, 0}, white = {0xffff, 0xffff, 0xffff};
+
+ if (!TkMacOSXSetupDrawingContext(dst, gc, 0, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ TkMacOSXDbgMsg("Ignored CG drawing of QD drawable");
+ goto end;
+ }
+ if (!dc.port) {
+ TkMacOSXDbgMsg("Invalid destination drawable");
+ goto end;
+ }
+ srcBit = GetPortBitMapForCopyBits(srcPort);
+ dstBit = GetPortBitMapForCopyBits(dc.port);
+ SetRect(srcPtr, srcDraw->xOff + src_x, srcDraw->yOff + src_y,
+ srcDraw->xOff + src_x + width,
+ srcDraw->yOff + src_y + height);
+ if (tkPictureIsOpen) {
+ dstPtr = srcPtr;
+ } else {
+ SetRect(dstPtr, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y,
+ dstDraw->xOff + dest_x + width,
+ dstDraw->yOff + dest_y + height);
+ }
+ RGBForeColor(&black);
+ RGBBackColor(&white);
+ CopyBits(srcBit, dstBit, srcPtr, dstPtr, srcCopy, NULL);
+end:
+ TkMacOSXRestoreDrawingContext(&dc);
+ } else {
+ TkMacOSXDbgMsg("Invalid source drawable");
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XCopyPlane --
+ *
+ * Copies a bitmap from a source drawable to a destination
+ * drawable. The plane argument specifies which bit plane of
+ * the source contains the bitmap. Note that this implementation
+ * ignores the gc->function.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Changes the destination drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XCopyPlane(
+ Display *display, /* Display. */
+ Drawable src, /* Source drawable. */
+ Drawable dst, /* Destination drawable. */
+ GC gc, /* GC to use. */
+ int src_x, /* X & Y, width & height */
+ int src_y, /* define the source rectangle */
+ unsigned int width, /* that will be copied. */
+ unsigned int height,
+ int dest_x, /* Dest X & Y on dest rect. */
+ int dest_y,
+ unsigned long plane) /* Which plane to copy. */
+{
+ TkMacOSXDrawingContext dc;
+ MacDrawable *srcDraw = (MacDrawable *) src, *dstDraw = (MacDrawable *) dst;
+
+ display->request++;
+ if (!width || !height) {
+ /* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */
+ return;
+ }
+ if (plane != 1) {
+ Tcl_Panic("Unexpected plane specified for XCopyPlane");
+ }
+ {
+ CGrafPtr srcPort;
+
+ srcPort = TkMacOSXGetDrawablePort(src);
+ if (srcPort) {
+ Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect;
+ const BitMap *srcBit, *dstBit;
+ TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask;
+
+ if (!TkMacOSXSetupDrawingContext(dst, gc, 0, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ TkMacOSXDbgMsg("Ignored CG drawing of QD drawable");
+ goto end;
+ }
+ if (!dc.port) {
+ TkMacOSXDbgMsg("Invalid destination drawable");
+ goto end;
+ }
+ srcBit = GetPortBitMapForCopyBits(srcPort);
+ dstBit = GetPortBitMapForCopyBits(dc.port);
+ SetRect(srcPtr, srcDraw->xOff + src_x, srcDraw->yOff + src_y,
+ srcDraw->xOff + src_x + width,
+ srcDraw->yOff + src_y + height);
+ if (tkPictureIsOpen) {
+ dstPtr = srcPtr;
+ } else {
+ SetRect(dstPtr, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y,
+ dstDraw->xOff + dest_x + width,
+ dstDraw->yOff + dest_y + height);
+ }
+ TkMacOSXSetColorInPort(gc->foreground, 1, NULL, dc.port);
+ if (!clipPtr || clipPtr->type == TKP_CLIP_REGION) {
+ /*
+ * Opaque bitmaps.
+ */
+
+ TkMacOSXSetColorInPort(gc->background, 0, NULL, dc.port);
+ CopyBits(srcBit, dstBit, srcPtr, dstPtr, srcCopy, NULL);
+ } else if (clipPtr->type == TKP_CLIP_PIXMAP) {
+ if (clipPtr->value.pixmap == src) {
+ /*
+ * Transparent bitmaps. If it's color ignore the forecolor.
+ */
+ short tmode = GetPixDepth(GetPortPixMap(srcPort)) == 1 ?
+ srcOr : transparent;
+
+ CopyBits(srcBit, dstBit, srcPtr, dstPtr, tmode, NULL);
+ } else {
+ /*
+ * Two arbitrary bitmaps.
+ */
+
+ CGrafPtr mskPort = TkMacOSXGetDrawablePort(
+ clipPtr->value.pixmap);
+ const BitMap *mskBit = GetPortBitMapForCopyBits(mskPort);
+
+ CopyDeepMask(srcBit, mskBit, dstBit, srcPtr, srcPtr,
+ dstPtr, srcCopy, NULL);
+ }
+ }
+end:
+ TkMacOSXRestoreDrawingContext(&dc);
+ } else {
+ TkMacOSXDbgMsg("Invalid source drawable");
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkPutImage --
+ *
+ * Copies a subimage from an in-memory image to a rectangle of
+ * of the specified drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws the image on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkPutImage(
+ unsigned long *colors, /* Unused on Macintosh. */
+ int ncolors, /* Unused on Macintosh. */
+ Display* display, /* Display. */
+ Drawable d, /* Drawable to place image on. */
+ GC gc, /* GC to use. */
+ XImage* image, /* Image to place. */
+ int src_x, /* Source X & Y. */
+ int src_y,
+ int dest_x, /* Destination X & Y. */
+ int dest_y,
+ unsigned int width, /* Same width & height for both */
+ unsigned int height) /* distination and source. */
+{
+ TkMacOSXDrawingContext dc;
+ MacDrawable *dstDraw = (MacDrawable *) d;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, 0, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ TkMacOSXDbgMsg("Ignored CG drawing of XImage");
+ } else {
+ Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect;
+ const BitMap *dstBit;
+ RGBColor black = {0, 0, 0}, white = {0xffff, 0xffff, 0xffff};
+ int i, j;
+ char *newData = NULL;
+ char *dataPtr, *newPtr, *oldPtr;
+ int rowBytes = image->bytes_per_line, sliceRowBytes, lastSliceRowBytes;
+ int slices, sliceWidth, lastSliceWidth;
+
+ dstBit = GetPortBitMapForCopyBits(dc.port);
+ SetRect(srcPtr, src_x, src_y, src_x + width, src_y + height);
+ if (tkPictureIsOpen) {
+ dstPtr = srcPtr;
+ } else {
+ SetRect(dstPtr, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y,
+ dstDraw->xOff + dest_x + width,
+ dstDraw->yOff + dest_y + height);
+ }
+ RGBForeColor(&black);
+ RGBBackColor(&white);
+ if (image->obdata) {
+ /*
+ * Image from XGetImage, copy from containing GWorld directly.
+ */
+
+ CopyBits(GetPortBitMapForCopyBits(TkMacOSXGetDrawablePort(
+ (Drawable)image->obdata)), dstBit,
+ srcPtr, dstPtr, srcCopy, NULL);
+ } else if (image->depth == 1) {
+ /*
+ * BW image
+ */
+
+ const int maxRowBytes = 0x3ffe;
+ BitMap bitmap;
+ int odd;
+
+ if (rowBytes > maxRowBytes) {
+ slices = rowBytes / maxRowBytes;
+ sliceRowBytes = maxRowBytes;
+ lastSliceRowBytes = rowBytes - (slices * maxRowBytes);
+ if (!lastSliceRowBytes) {
+ slices--;
+ lastSliceRowBytes = maxRowBytes;
+ }
+ sliceWidth = (long) image->width * maxRowBytes / rowBytes;
+ lastSliceWidth = image->width - (sliceWidth * slices);
+ } else {
+ slices = 0;
+ sliceRowBytes = lastSliceRowBytes = rowBytes;
+ sliceWidth = lastSliceWidth = image->width;
+ }
+ bitmap.bounds.top = bitmap.bounds.left = 0;
+ bitmap.bounds.bottom = (short) image->height;
+ dataPtr = image->data + image->xoffset;
+ do {
+ if (slices) {
+ bitmap.bounds.right = bitmap.bounds.left + sliceWidth;
+ } else {
+ sliceRowBytes = lastSliceRowBytes;
+ bitmap.bounds.right = bitmap.bounds.left + lastSliceWidth;
+ }
+ oldPtr = dataPtr;
+ odd = sliceRowBytes % 2;
+ if (!newData) {
+ newData = ckalloc(image->height * (sliceRowBytes+odd));
+ }
+ newPtr = newData;
+ if (image->bitmap_bit_order != MSBFirst) {
+ for (i = 0; i < image->height; i++) {
+ for (j = 0; j < sliceRowBytes; j++) {
+ *newPtr = xBitReverseTable[(unsigned char)*oldPtr];
+ newPtr++; oldPtr++;
+ }
+ if (odd) {
+ *newPtr++ = 0;
+ }
+ oldPtr += rowBytes - sliceRowBytes;
+ }
+ } else {
+ for (i = 0; i < image->height; i++) {
+ memcpy(newPtr, oldPtr, sliceRowBytes);
+ newPtr += sliceRowBytes;
+ if (odd) {
+ *newPtr++ = 0;
+ }
+ oldPtr += rowBytes;
+ }
+ }
+ bitmap.baseAddr = newData;
+ bitmap.rowBytes = sliceRowBytes + odd;
+ CopyBits(&bitmap, dstBit, srcPtr, dstPtr, srcCopy, NULL);
+ if (slices) {
+ bitmap.bounds.left = bitmap.bounds.right;
+ dataPtr += sliceRowBytes;
+ }
+ } while (slices--);
+ ckfree(newData);
+ } else {
+ /*
+ * Color image
+ */
+
+ const int maxRowBytes = 0x3ffc;
+ PixMap pixmap;
+
+ pixmap.bounds.left = 0;
+ pixmap.bounds.top = 0;
+ pixmap.bounds.bottom = (short) image->height;
+ pixmap.pixelType = RGBDirect;
+ pixmap.pmVersion = baseAddr32; /* 32bit clean */
+ pixmap.packType = 0;
+ pixmap.packSize = 0;
+ pixmap.hRes = 0x00480000;
+ pixmap.vRes = 0x00480000;
+ pixmap.pixelSize = 32;
+ pixmap.cmpCount = 3;
+ pixmap.cmpSize = 8;
+ pixmap.pixelFormat = image->byte_order == MSBFirst ?
+ k32ARGBPixelFormat : k32BGRAPixelFormat;
+ pixmap.pmTable = NULL;
+ pixmap.pmExt = 0;
+ if (rowBytes > maxRowBytes) {
+ slices = rowBytes / maxRowBytes;
+ sliceRowBytes = maxRowBytes;
+ lastSliceRowBytes = rowBytes - (slices * maxRowBytes);
+ if (!lastSliceRowBytes) {
+ slices--;
+ lastSliceRowBytes = maxRowBytes;
+ }
+ sliceWidth = (long) image->width * maxRowBytes / rowBytes;
+ lastSliceWidth = image->width - (sliceWidth * slices);
+ dataPtr = image->data + image->xoffset;
+ newData = ckalloc(image->height * sliceRowBytes);
+ do {
+ if (slices) {
+ pixmap.bounds.right = pixmap.bounds.left + sliceWidth;
+ } else {
+ sliceRowBytes = lastSliceRowBytes;
+ pixmap.bounds.right = pixmap.bounds.left + lastSliceWidth;
+ }
+ oldPtr = dataPtr;
+ newPtr = newData;
+ for (i = 0; i < image->height; i++) {
+ memcpy(newPtr, oldPtr, sliceRowBytes);
+ oldPtr += rowBytes;
+ newPtr += sliceRowBytes;
+ }
+ pixmap.baseAddr = newData;
+ pixmap.rowBytes = sliceRowBytes | 0x8000;
+ CopyBits((BitMap*) &pixmap, dstBit, srcPtr, dstPtr, srcCopy,
+ NULL);
+ if (slices) {
+ pixmap.bounds.left = pixmap.bounds.right;
+ dataPtr += sliceRowBytes;
+ }
+ } while (slices--);
+ ckfree(newData);
+ } else {
+ pixmap.bounds.right = (short) image->width;
+ pixmap.baseAddr = image->data + image->xoffset;
+ pixmap.rowBytes = rowBytes | 0x8000;
+ CopyBits((BitMap*) &pixmap, dstBit, srcPtr, dstPtr, srcCopy, NULL);
+ }
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawLines --
+ *
+ * Draw connected lines.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Renders a series of connected lines.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawLines(
+ Display *display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ XPoint *points, /* Array of points. */
+ int npoints, /* Number of points. */
+ int mode) /* Line drawing mode. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ int i, lw = gc->line_width;
+
+ if (npoints < 2) {
+ /*
+ * TODO: generate BadValue error.
+ */
+
+ return;
+ }
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ double prevx, prevy;
+ double o = (lw % 2) ? .5 : 0;
+
+ CGContextBeginPath(dc.context);
+ prevx = macWin->xOff + points[0].x + o;
+ prevy = macWin->yOff + points[0].y + o;
+ CGContextMoveToPoint(dc.context, prevx, prevy);
+ for (i = 1; i < npoints; i++) {
+ if (mode == CoordModeOrigin) {
+ CGContextAddLineToPoint(dc.context,
+ macWin->xOff + points[i].x + o,
+ macWin->yOff + points[i].y + o);
+ } else {
+ prevx += points[i].x;
+ prevy += points[i].y;
+ CGContextAddLineToPoint(dc.context, prevx, prevy);
+ }
+ }
+ CGContextStrokePath(dc.context);
+ } else {
+ int o = -lw/2;
+
+ /* This is broken for fat lines, it is not possible to correctly
+ * imitate X11 drawing of oblique fat lines with QD line drawing,
+ * we should draw a filled polygon instead. */
+
+ MoveTo((short) (macWin->xOff + points[0].x + o),
+ (short) (macWin->yOff + points[0].y + o));
+ for (i = 1; i < npoints; i++) {
+ if (mode == CoordModeOrigin) {
+ LineTo((short) (macWin->xOff + points[i].x + o),
+ (short) (macWin->yOff + points[i].y + o));
+ } else {
+ Line((short) points[i].x, (short) points[i].y);
+ }
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawSegments --
+ *
+ * Draw unconnected lines.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Renders a series of unconnected lines.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawSegments(
+ Display *display,
+ Drawable d,
+ GC gc,
+ XSegment *segments,
+ int nsegments)
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ int i, lw = gc->line_width;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ double o = (lw % 2) ? .5 : 0;
+
+ for (i = 0; i < nsegments; i++) {
+ CGContextBeginPath(dc.context);
+ CGContextMoveToPoint(dc.context,
+ macWin->xOff + segments[i].x1 + o,
+ macWin->yOff + segments[i].y1 + o);
+ CGContextAddLineToPoint(dc.context,
+ macWin->xOff + segments[i].x2 + o,
+ macWin->yOff + segments[i].y2 + o);
+ CGContextStrokePath(dc.context);
+ }
+ } else {
+ int o = -lw/2;
+
+ /* This is broken for fat lines, it is not possible to correctly
+ * imitate X11 drawing of oblique fat lines with QD line drawing,
+ * we should draw a filled polygon instead. */
+
+ for (i = 0; i < nsegments; i++) {
+ MoveTo((short) (macWin->xOff + segments[i].x1 + o),
+ (short) (macWin->yOff + segments[i].y1 + o));
+ LineTo((short) (macWin->xOff + segments[i].x2 + o),
+ (short) (macWin->yOff + segments[i].y2 + o));
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFillPolygon --
+ *
+ * Draws a filled polygon.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws a filled polygon on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XFillPolygon(
+ Display* display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ XPoint* points, /* Array of points. */
+ int npoints, /* Number of points. */
+ int shape, /* Shape to draw. */
+ int mode) /* Drawing mode. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ int i;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ double prevx, prevy;
+ double o = (gc->line_width % 2) ? .5 : 0;
+
+ CGContextBeginPath(dc.context);
+ prevx = macWin->xOff + points[0].x + o;
+ prevy = macWin->yOff + points[0].y + o;
+ CGContextMoveToPoint(dc.context, prevx, prevy);
+ for (i = 1; i < npoints; i++) {
+ if (mode == CoordModeOrigin) {
+ CGContextAddLineToPoint(dc.context,
+ macWin->xOff + points[i].x + o,
+ macWin->yOff + points[i].y + o);
+ } else {
+ prevx += points[i].x;
+ prevy += points[i].y;
+ CGContextAddLineToPoint(dc.context, prevx, prevy);
+ }
+ }
+ CGContextEOFillPath(dc.context);
+ } else {
+ PolyHandle polygon;
+
+ polygon = OpenPoly();
+ MoveTo((short) (macWin->xOff + points[0].x),
+ (short) (macWin->yOff + points[0].y));
+ for (i = 1; i < npoints; i++) {
+ if (mode == CoordModeOrigin) {
+ LineTo((short) (macWin->xOff + points[i].x),
+ (short) (macWin->yOff + points[i].y));
+ } else {
+ Line((short) points[i].x, (short) points[i].y);
+ }
+ }
+ ClosePoly();
+ FillCPoly(polygon, dc.penPat);
+ KillPoly(polygon);
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawRectangle --
+ *
+ * Draws a rectangle.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws a rectangle on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawRectangle(
+ Display *display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ int x, int y, /* Upper left corner. */
+ unsigned int width, /* Width & height of rect. */
+ unsigned int height)
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ int lw = gc->line_width;
+
+ if (width == 0 || height == 0) {
+ return;
+ }
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+ double o = (lw % 2) ? .5 : 0;
+
+ rect = CGRectMake(
+ macWin->xOff + x + o,
+ macWin->yOff + y + o,
+ width, height);
+ CGContextStrokeRect(dc.context, rect);
+ } else {
+ Rect theRect;
+ int o = -lw/2;
+
+ theRect.left = (short) (macWin->xOff + x + o);
+ theRect.top = (short) (macWin->yOff + y + o);
+ theRect.right = (short) (theRect.left + width + lw);
+ theRect.bottom = (short) (theRect.top + height + lw);
+ FrameRect(&theRect);
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+#ifdef TK_MACOSXDRAW_UNUSED
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawRectangles --
+ *
+ * Draws the outlines of the specified rectangles as if a
+ * five-point PolyLine protocol request were specified for each
+ * rectangle:
+ *
+ * [x,y] [x+width,y] [x+width,y+height] [x,y+height] [x,y]
+ *
+ * For the specified rectangles, these functions do not draw a
+ * pixel more than once. XDrawRectangles draws the rectangles in
+ * the order listed in the array. If rectangles intersect, the
+ * intersecting pixels are drawn multiple times. Draws a
+ * rectangle.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws rectangles on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawRectangles(
+ Display *display,
+ Drawable drawable,
+ GC gc,
+ XRectangle *rectArr,
+ int nRects)
+{
+ MacDrawable *macWin = (MacDrawable *) drawable;
+ TkMacOSXDrawingContext dc;
+ XRectangle * rectPtr;
+ int i, lw = gc->line_width;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+ double o = (lw % 2) ? .5 : 0;
+
+ for (i = 0, rectPtr = rectArr; i < nRects; i++, rectPtr++) {
+ if (rectPtr->width == 0 || rectPtr->height == 0) {
+ continue;
+ }
+ rect = CGRectMake(
+ macWin->xOff + rectPtr->x + o,
+ macWin->yOff + rectPtr->y + o,
+ rectPtr->width, rectPtr->height);
+ CGContextStrokeRect(dc.context, rect);
+ }
+ } else {
+ Rect theRect;
+ int o = -lw/2;
+
+ for (i = 0, rectPtr = rectArr; i < nRects;i++, rectPtr++) {
+ theRect.left = (short) (macWin->xOff + rectPtr->x + o);
+ theRect.top = (short) (macWin->yOff + rectPtr->y + o);
+ theRect.right = (short) (theRect.left + rectPtr->width + lw);
+ theRect.bottom = (short) (theRect.top + rectPtr->height + lw);
+ FrameRect(&theRect);
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFillRectangles --
+ *
+ * Fill multiple rectangular areas in the given drawable.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws onto the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XFillRectangles(
+ Display* display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ XRectangle *rectangles, /* Rectangle array. */
+ int n_rectangles) /* Number of rectangles. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ XRectangle * rectPtr;
+ int i;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+
+ for (i = 0, rectPtr = rectangles; i < n_rectangles; i++, rectPtr++) {
+ if (rectPtr->width == 0 || rectPtr->height == 0) {
+ continue;
+ }
+ rect = CGRectMake(
+ macWin->xOff + rectPtr->x,
+ macWin->yOff + rectPtr->y,
+ rectPtr->width, rectPtr->height);
+ CGContextFillRect(dc.context, rect);
+ }
+ } else {
+ Rect theRect;
+
+ for (i = 0, rectPtr = rectangles; i < n_rectangles; i++, rectPtr++) {
+ theRect.left = (short) (macWin->xOff + rectPtr->x);
+ theRect.top = (short) (macWin->yOff + rectPtr->y);
+ theRect.right = (short) (theRect.left + rectPtr->width);
+ theRect.bottom = (short) (theRect.top + rectPtr->height);
+ FillCRect(&theRect, dc.penPat);
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawArc --
+ *
+ * Draw an arc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws an arc on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawArc(
+ Display* display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ int x, int y, /* Upper left of bounding rect. */
+ unsigned int width, /* Width & height. */
+ unsigned int height,
+ int angle1, /* Staring angle of arc. */
+ int angle2) /* Extent of arc. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ int lw = gc->line_width;
+
+ if (width == 0 || height == 0 || angle2 == 0) {
+ return;
+ }
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+ double o = (lw % 2) ? .5 : 0;
+
+ rect = CGRectMake(
+ macWin->xOff + x + o,
+ macWin->yOff + y + o,
+ width, height);
+ TK_IF_MAC_OS_X_API_COND (4, CGContextStrokeEllipseInRect,
+ angle1 == 0 && angle2 == 23040,
+ CGContextStrokeEllipseInRect(dc.context, rect);
+ ) TK_ELSE (
+ CGMutablePathRef p = CGPathCreateMutable();
+ CGAffineTransform t = CGAffineTransformIdentity;
+ CGPoint c = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
+ double w = CGRectGetWidth(rect);
+
+ if (width != height) {
+ t = CGAffineTransformMakeScale(1.0, CGRectGetHeight(rect)/w);
+ c = CGPointApplyAffineTransform(c, CGAffineTransformInvert(t));
+ }
+ CGPathAddArc(p, &t, c.x, c.y, w/2, radians(-angle1/64.0),
+ radians(-(angle1 + angle2)/64.0), angle2 > 0);
+ CGContextAddPath(dc.context, p);
+ CGPathRelease(p);
+ CGContextStrokePath(dc.context);
+ ) TK_ENDIF
+ } else {
+ Rect theRect;
+ short start, extent;
+ int o = -lw/2;
+
+ theRect.left = (short) (macWin->xOff + x + o);
+ theRect.top = (short) (macWin->yOff + y + o);
+ theRect.right = (short) (theRect.left + width + lw);
+ theRect.bottom = (short) (theRect.top + height + lw);
+ start = (short) (90 - (angle1/64));
+ extent = (short) (-(angle2/64));
+ FrameArc(&theRect, start, extent);
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+#ifdef TK_MACOSXDRAW_UNUSED
+/*
+ *----------------------------------------------------------------------
+ *
+ * XDrawArcs --
+ *
+ * Draws multiple circular or elliptical arcs. Each arc is
+ * specified by a rectangle and two angles. The center of the
+ * circle or ellipse is the center of the rect- angle, and the
+ * major and minor axes are specified by the width and height.
+ * Positive angles indicate counterclock- wise motion, and
+ * negative angles indicate clockwise motion. If the magnitude
+ * of angle2 is greater than 360 degrees, XDrawArcs truncates it
+ * to 360 degrees.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws an arc for each array element on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XDrawArcs(
+ Display *display,
+ Drawable d,
+ GC gc,
+ XArc *arcArr,
+ int nArcs)
+{
+
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ XArc *arcPtr;
+ int i, lw = gc->line_width;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+ double o = (lw % 2) ? .5 : 0;
+
+ for (i=0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) {
+ if (arcPtr->width == 0 || arcPtr->height == 0
+ || arcPtr->angle2 == 0) {
+ continue;
+ }
+ rect = CGRectMake(
+ macWin->xOff + arcPtr->x + o,
+ macWin->yOff + arcPtr->y + o,
+ arcPtr->width, arcPtr->height);
+
+ TK_IF_MAC_OS_X_API_COND (4, CGContextStrokeEllipseInRect,
+ arcPtr->angle1 == 0 && arcPtr->angle2 == 23040,
+ CGContextStrokeEllipseInRect(dc.context, rect);
+ ) TK_ELSE (
+ CGMutablePathRef p = CGPathCreateMutable();
+ CGAffineTransform t = CGAffineTransformIdentity;
+ CGPoint c = CGPointMake(CGRectGetMidX(rect),
+ CGRectGetMidY(rect));
+ double w = CGRectGetWidth(rect);
+
+ if (arcPtr->width != arcPtr->height) {
+ t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w);
+ c = CGPointApplyAffineTransform(c,
+ CGAffineTransformInvert(t));
+ }
+ CGPathAddArc(p, &t, c.x, c.y, w/2,
+ radians(-arcPtr->angle1/64.0),
+ radians(-(arcPtr->angle1 + arcPtr->angle2)/64.0),
+ arcPtr->angle2 > 0);
+ CGContextAddPath(dc.context, p);
+ CGPathRelease(p);
+ CGContextStrokePath(dc.context);
+ ) TK_ENDIF
+ }
+ } else {
+ Rect theRect;
+ short start, extent;
+ int o = -lw/2;
+
+ for (i = 0, arcPtr = arcArr;i < nArcs;i++, arcPtr++) {
+ theRect.left = (short) (macWin->xOff + arcPtr->x + o);
+ theRect.top = (short) (macWin->yOff + arcPtr->y + o);
+ theRect.right = (short) (theRect.left + arcPtr->width + lw);
+ theRect.bottom = (short) (theRect.top + arcPtr->height + lw);
+ start = (short) (90 - (arcPtr->angle1/64));
+ extent = (short) (-(arcPtr->angle2/64));
+ FrameArc(&theRect, start, extent);
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFillArc --
+ *
+ * Draw a filled arc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws a filled arc on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XFillArc(
+ Display* display, /* Display. */
+ Drawable d, /* Draw on this. */
+ GC gc, /* Use this GC. */
+ int x, int y, /* Upper left of bounding rect. */
+ unsigned int width, /* Width & height. */
+ unsigned int height,
+ int angle1, /* Staring angle of arc. */
+ int angle2) /* Extent of arc. */
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ int lw = gc->line_width;
+
+ if (width == 0 || height == 0 || angle2 == 0) {
+ return;
+ }
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+ double o = (lw % 2) ? .5 : 0, u = 0;
+
+ if (notAA(lw)) {
+ o += NON_AA_CG_OFFSET/2;
+ u += NON_AA_CG_OFFSET;
+ }
+ rect = CGRectMake(
+ macWin->xOff + x + o,
+ macWin->yOff + y + o,
+ width - u, height - u);
+
+ TK_IF_MAC_OS_X_API_COND (4, CGContextFillEllipseInRect,
+ angle1 == 0 && angle2 == 23040,
+ CGContextFillEllipseInRect(dc.context, rect);
+ ) TK_ELSE (
+ CGMutablePathRef p = CGPathCreateMutable();
+ CGAffineTransform t = CGAffineTransformIdentity;
+ CGPoint c = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
+ double w = CGRectGetWidth(rect);
+
+ if (width != height) {
+ t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w);
+ c = CGPointApplyAffineTransform(c, CGAffineTransformInvert(t));
+ }
+ if (gc->arc_mode == ArcPieSlice) {
+ CGPathMoveToPoint(p, &t, c.x, c.y);
+ }
+ CGPathAddArc(p, &t, c.x, c.y, w/2, radians(-angle1/64.0),
+ radians(-(angle1 + angle2)/64.0), angle2 > 0);
+ CGPathCloseSubpath(p);
+ CGContextAddPath(dc.context, p);
+ CGPathRelease(p);
+ CGContextFillPath(dc.context);
+ ) TK_ENDIF
+ } else {
+ Rect theRect;
+ short start, extent;
+ int o = -lw/2;
+ PolyHandle polygon;
+ double sin1, cos1, sin2, cos2, angle;
+ double boxWidth, boxHeight;
+ double vertex[2], center1[2], center2[2];
+
+ theRect.left = (short) (macWin->xOff + x + o);
+ theRect.top = (short) (macWin->yOff + y + o);
+ theRect.right = (short) (theRect.left + width + lw);
+ theRect.bottom = (short) (theRect.top + height + lw);
+ start = (short) (90 - (angle1/64));
+ extent = (short) (-(angle2/64));
+ if (gc->arc_mode == ArcChord) {
+ boxWidth = theRect.right - theRect.left;
+ boxHeight = theRect.bottom - theRect.top;
+ angle = radians(-angle1/64.0);
+ sin1 = sin(angle);
+ cos1 = cos(angle);
+ angle -= radians(angle2/64.0);
+ sin2 = sin(angle);
+ cos2 = cos(angle);
+ vertex[0] = (theRect.left + theRect.right)/2.0;
+ vertex[1] = (theRect.top + theRect.bottom)/2.0;
+ center1[0] = vertex[0] + cos1*boxWidth/2.0;
+ center1[1] = vertex[1] + sin1*boxHeight/2.0;
+ center2[0] = vertex[0] + cos2*boxWidth/2.0;
+ center2[1] = vertex[1] + sin2*boxHeight/2.0;
+
+ polygon = OpenPoly();
+ MoveTo((short) ((theRect.left + theRect.right)/2),
+ (short) ((theRect.top + theRect.bottom)/2));
+ LineTo((short) (center1[0] + .5), (short) (center1[1] + .5));
+ LineTo((short) (center2[0] + .5), (short) (center2[1] + .5));
+ ClosePoly();
+ FillCArc(&theRect, start, extent, dc.penPat);
+ FillCPoly(polygon, dc.penPat);
+ KillPoly(polygon);
+ } else {
+ FillCArc(&theRect, start, extent, dc.penPat);
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+
+#ifdef TK_MACOSXDRAW_UNUSED
+/*
+ *----------------------------------------------------------------------
+ *
+ * XFillArcs --
+ *
+ * Draw a filled arc.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws a filled arc for each array element on the specified drawable.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+XFillArcs(
+ Display *display,
+ Drawable d,
+ GC gc,
+ XArc *arcArr,
+ int nArcs)
+{
+ MacDrawable *macWin = (MacDrawable *) d;
+ TkMacOSXDrawingContext dc;
+ XArc * arcPtr;
+ int i, lw = gc->line_width;
+
+ display->request++;
+ if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) {
+ return;
+ }
+ if (dc.context) {
+ CGRect rect;
+ double o = (lw % 2) ? .5 : 0, u = 0;
+
+ if (notAA(lw)) {
+ o += NON_AA_CG_OFFSET/2;
+ u += NON_AA_CG_OFFSET;
+ }
+ for (i = 0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) {
+ if (arcPtr->width == 0 || arcPtr->height == 0
+ || arcPtr->angle2 == 0) {
+ continue;
+ }
+ rect = CGRectMake(
+ macWin->xOff + arcPtr->x + o,
+ macWin->yOff + arcPtr->y + o,
+ arcPtr->width - u, arcPtr->height - u);
+ TK_IF_MAC_OS_X_API_COND (4, CGContextFillEllipseInRect,
+ arcPtr->angle1 == 0 && arcPtr->angle2 == 23040,
+ CGContextFillEllipseInRect(dc.context, rect);
+ ) TK_ELSE (
+ CGMutablePathRef p = CGPathCreateMutable();
+ CGAffineTransform t = CGAffineTransformIdentity;
+ CGPoint c = CGPointMake(CGRectGetMidX(rect),
+ CGRectGetMidY(rect));
+ double w = CGRectGetWidth(rect);
+
+ if (arcPtr->width != arcPtr->height) {
+ t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w);
+ c = CGPointApplyAffineTransform(c,
+ CGAffineTransformInvert(t));
+ }
+ if (gc->arc_mode == ArcPieSlice) {
+ CGPathMoveToPoint(p, &t, c.x, c.y);
+ }
+ CGPathAddArc(p, &t, c.x, c.y, w/2,
+ radians(-arcPtr->angle1/64.0),
+ radians(-(arcPtr->angle1 + arcPtr->angle2)/64.0),
+ arcPtr->angle2 > 0);
+ CGPathCloseSubpath(p);
+ CGContextAddPath(dc.context, p);
+ CGPathRelease(p);
+ CGContextFillPath(dc.context);
+ ) TK_ENDIF
+ }
+ } else {
+ Rect theRect;
+ short start, extent;
+ int o = -lw/2;
+ PolyHandle polygon;
+ double sin1, cos1, sin2, cos2, angle;
+ double boxWidth, boxHeight;
+ double vertex[2], center1[2], center2[2];
+
+ for (i = 0, arcPtr = arcArr;i<nArcs;i++, arcPtr++) {
+ theRect.left = (short) (macWin->xOff + arcPtr->x + o);
+ theRect.top = (short) (macWin->yOff + arcPtr->y + o);
+ theRect.right = (short) (theRect.left + arcPtr->width + lw);
+ theRect.bottom = (short) (theRect.top + arcPtr->height + lw);
+ start = (short) (90 - (arcPtr->angle1/64));
+ extent = (short) (- (arcPtr->angle2/64));
+
+ if (gc->arc_mode == ArcChord) {
+ boxWidth = theRect.right - theRect.left;
+ boxHeight = theRect.bottom - theRect.top;
+ angle = radians(-arcPtr->angle1/64.0);
+ sin1 = sin(angle);
+ cos1 = cos(angle);
+ angle -= radians(arcPtr->angle2/64.0);
+ sin2 = sin(angle);
+ cos2 = cos(angle);
+ vertex[0] = (theRect.left + theRect.right)/2.0;
+ vertex[1] = (theRect.top + theRect.bottom)/2.0;
+ center1[0] = vertex[0] + cos1*boxWidth/2.0;
+ center1[1] = vertex[1] + sin1*boxHeight/2.0;
+ center2[0] = vertex[0] + cos2*boxWidth/2.0;
+ center2[1] = vertex[1] + sin2*boxHeight/2.0;
+
+ polygon = OpenPoly();
+ MoveTo((short) ((theRect.left + theRect.right)/2),
+ (short) ((theRect.top + theRect.bottom)/2));
+ LineTo((short) (center1[0] + .5), (short) (center1[1] + .5));
+ LineTo((short) (center2[0] + .5), (short) (center2[1] + .5));
+ ClosePoly();
+ FillCArc(&theRect, start, extent, dc.penPat);
+ FillCPoly(polygon, dc.penPat);
+ KillPoly(polygon);
+ } else {
+ FillCArc(&theRect, start, extent, dc.penPat);
+ }
+ }
+ }
+ TkMacOSXRestoreDrawingContext(&dc);
+}
+#endif
+
+#ifdef TK_MACOSXDRAW_UNUSED
+/*
+ *----------------------------------------------------------------------
+ *
+ * XMaxRequestSize --
+ *
+ *----------------------------------------------------------------------
+ */
+
+long
+XMaxRequestSize(
+ Display *display)
+{
+ return (SHRT_MAX / 4);
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkScrollWindow --
+ *
+ * Scroll a rectangle of the specified window and accumulate
+ * a damage region.
+ *
+ * Results:
+ * Returns 0 if the scroll genereated no additional damage.
+ * Otherwise, sets the region that needs to be repainted after
+ * scrolling and returns 1.
+ *
+ * Side effects:
+ * Scrolls the bits in the window.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkScrollWindow(
+ Tk_Window tkwin, /* The window to be scrolled. */
+ GC gc, /* GC for window to be scrolled. */
+ int x, int y, /* Position rectangle to be scrolled. */
+ int width, int height,
+ int dx, int dy, /* Distance rectangle should be moved. */
+ TkRegion damageRgn) /* Region to accumulate damage in. */
+{
+ MacDrawable *destDraw = (MacDrawable *) Tk_WindowId(tkwin);
+ CGrafPtr destPort, savePort;
+ Boolean portChanged;
+ Rect scrollRect;
+ int result;
+ HIShapeRef dmgRgn;
+
+ /*
+ * Due to the implementation below the behavior may be differnt
+ * than X in certain cases that should never occur in Tk. The
+ * scrollRect is the source rect extended by the offset (the union
+ * of the source rect and the offset rect). Everything
+ * in the extended scrollRect is scrolled. On X, it's possible
+ * to "skip" over an area if the offset makes the source and
+ * destination rects disjoint and non-aligned.
+ */
+
+ scrollRect.left = destDraw->xOff + x;
+ scrollRect.top = destDraw->yOff + y;
+ scrollRect.right = scrollRect.left + width;
+ scrollRect.bottom = scrollRect.top + height;
+ if (dx < 0) {
+ scrollRect.left += dx;
+ } else {
+ scrollRect.right += dx;
+ }
+ if (dy < 0) {
+ scrollRect.top += dy;
+ } else {
+ scrollRect.bottom += dy;
+ }
+
+ destPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin));
+ TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin));
+ TkMacOSXCheckTmpQdRgnEmpty();
+ portChanged = QDSwapPort(destPort, &savePort);
+ ScrollRect(&scrollRect, dx, dy, tkMacOSXtmpQdRgn);
+ if (portChanged) {
+ QDSwapPort(savePort, NULL);
+ }
+
+ /*
+ * Fortunately, the region returned by ScrollRect is semantically
+ * the same as what we need to return in this function. If the
+ * region is empty we return zero to denote that no damage was
+ * created.
+ */
+
+ dmgRgn = HIShapeCreateWithQDRgn(tkMacOSXtmpQdRgn);
+ SetEmptyRgn(tkMacOSXtmpQdRgn);
+ TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn);
+ result = HIShapeIsEmpty(dmgRgn) ? 0 : 1;
+ CFRelease(dmgRgn);
+
+ return result;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXSetUpGraphicsPort --
+ *
+ * Set up the graphics port from the given GC.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The current port is adjusted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXSetUpGraphicsPort(
+ GC gc, /* GC to apply to current port. */
+ void *destPort)
+{
+ CGrafPtr savePort;
+ Boolean portChanged;
+
+ portChanged = QDSwapPort(destPort, &savePort);
+ PenNormal();
+ if (gc) {
+ if (!penPat) {
+ if (!tmpPixPat) {
+ penPat = NewPixPat();
+ } else {
+ penPat = tmpPixPat;
+ tmpPixPat = NULL;
+ }
+ }
+ TkMacOSXSetColorInPort(gc->foreground, 1, penPat, destPort);
+ PenPixPat(penPat);
+ if(gc->function == GXxor) {
+ PenMode(patXor);
+ }
+ if (gc->line_width > 1) {
+ PenSize(gc->line_width, gc->line_width);
+ }
+ if (gc->line_style != LineSolid) {
+ /*
+ * FIXME: Here the dash pattern should be set in the drawing
+ * environment. This is not possible with QuickDraw line drawing.
+ */
+ }
+ }
+ if (portChanged) {
+ QDSwapPort(savePort, NULL);
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXSetUpDrawingContext --
+ *
+ * Set up a drawing context for the given drawable and GC.
+ *
+ * Results:
+ * Boolean indicating whether it is ok to draw; if false, drawing
+ * context was not setup, so do not attempt to draw and do not call
+ * TkMacOSXRestoreDrawingContext().
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacOSXSetupDrawingContext(
+ Drawable d,
+ GC gc,
+ int useCG, /* advisory only ! */
+ TkMacOSXDrawingContext *dcPtr)
+{
+ MacDrawable *macDraw = ((MacDrawable*)d);
+ int dontDraw = 0;
+ TkMacOSXDrawingContext dc = {NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ {SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX}, false};
+
+ if (tkPictureIsOpen) {
+ if (useCG) {
+ TkMacOSXDbgMsg("Ignored CG Drawing with QD Picture open");
+ dontDraw = 1;
+ }
+ } else {
+ dc.clipRgn = TkMacOSXGetClipRgn(d);
+ }
+ if (!dontDraw) {
+ ClipToGC(d, gc, &dc.clipRgn);
+ dontDraw = dc.clipRgn ? HIShapeIsEmpty(dc.clipRgn) : 0;
+ }
+ if (dontDraw) {
+ if (dc.clipRgn) {
+ CFRelease(dc.clipRgn);
+ dc.clipRgn = NULL;
+ }
+ goto end;
+ }
+ if (useCG) {
+ dc.context = macDraw->context;
+ }
+ if (!dc.context || !(macDraw->flags & TK_IS_PIXMAP)) {
+ dc.port = TkMacOSXGetDrawablePort(d);
+ if (dc.port) {
+ GetPortBounds(dc.port, &dc.portBounds);
+ }
+ }
+ if (dc.context) {
+ if (!dc.port) {
+ CGRect r;
+
+ TK_IF_MAC_OS_X_API (3, CGContextGetClipBoundingBox,
+ r = CGContextGetClipBoundingBox(dc.context);
+ ) TK_ELSE_MAC_OS_X (3,
+ r.origin = CGPointZero;
+ r.size = macDraw->size;
+ ) TK_ENDIF
+ SetRect(&dc.portBounds, r.origin.x + macDraw->xOff,
+ r.origin.y + macDraw->yOff,
+ r.origin.x + r.size.width + macDraw->xOff,
+ r.origin.y + r.size.height + macDraw->yOff);
+ }
+ CGContextSaveGState(dc.context);
+ dc.saveState = (void*)1;
+ dc.port = NULL;
+ } else if (dc.port) {
+ dc.portChanged = QDSwapPort(dc.port, &dc.savePort);
+ if (useCG && ChkErr(QDBeginCGContext, dc.port, &dc.context) == noErr) {
+ SyncCGContextOriginWithPort(dc.context, dc.port);
+ } else {
+ dc.context = NULL;
+ }
+ } else {
+ Tcl_Panic("TkMacOSXSetupDrawingContext(): "
+ "no port or context to draw into !");
+ }
+ if (dc.context) {
+ CGContextConcatCTM(dc.context, CGAffineTransformMake(1.0, 0.0, 0.0,
+ -1.0, 0.0, dc.portBounds.bottom - dc.portBounds.top));
+ if (dc.clipRgn) {
+#ifdef TK_MAC_DEBUG_DRAWING
+ CGContextSaveGState(dc.context);
+ ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);
+ CGContextSetRGBFillColor(dc.context, 1.0, 0.0, 0.0, 0.2);
+ CGContextEOFillPath(dc.context);
+ CGContextRestoreGState(dc.context);
+#endif /* TK_MAC_DEBUG_DRAWING */
+ ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context);
+ CGContextEOClip(dc.context);
+ }
+ if (gc) {
+ static const CGLineCap cgCap[] = {
+ [CapNotLast] = kCGLineCapButt,
+ [CapButt] = kCGLineCapButt,
+ [CapRound] = kCGLineCapRound,
+ [CapProjecting] = kCGLineCapSquare,
+ };
+ static const CGLineJoin cgJoin[] = {
+ [JoinMiter] = kCGLineJoinMiter,
+ [JoinRound] = kCGLineJoinRound,
+ [JoinBevel] = kCGLineJoinBevel,
+ };
+ bool shouldAntialias;
+ double w = gc->line_width;
+
+ TkMacOSXSetColorInContext(gc->foreground, dc.context);
+ if (dc.port) {
+ CGContextSetPatternPhase(dc.context, CGSizeMake(
+ dc.portBounds.right - dc.portBounds.left,
+ dc.portBounds.bottom - dc.portBounds.top));
+ }
+ if(gc->function != GXcopy) {
+ TkMacOSXDbgMsg("Logical functions other than GXcopy are "
+ "not supported for CG drawing!");
+ }
+ /* When should we antialias? */
+ shouldAntialias = !notAA(gc->line_width);
+ if (!shouldAntialias) {
+ /* Make non-antialiased CG drawing look more like X11 */
+ w -= (gc->line_width ? NON_AA_CG_OFFSET : 0);
+ }
+ CGContextSetShouldAntialias(dc.context, shouldAntialias);
+ CGContextSetLineWidth(dc.context, w);
+ if (gc->line_style != LineSolid) {
+ int num = 0;
+ char *p = &(gc->dashes);
+ double dashOffset = gc->dash_offset;
+ float lengths[10];
+
+ while (p[num] != '\0' && num < 10) {
+ lengths[num] = p[num];
+ num++;
+ }
+ CGContextSetLineDash(dc.context, dashOffset, lengths, num);
+ }
+ if ((unsigned)gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) {
+ CGContextSetLineCap(dc.context,
+ cgCap[(unsigned)gc->cap_style]);
+ }
+ if ((unsigned)gc->join_style < sizeof(cgJoin)/sizeof(CGLineJoin)) {
+ CGContextSetLineJoin(dc.context,
+ cgJoin[(unsigned)gc->join_style]);
+ }
+ }
+ } else if (dc.port) {
+ PixPatHandle savePat = penPat;
+
+ ChkErr(GetThemeDrawingState, &dc.saveState);
+ penPat = NULL;
+ TkMacOSXSetUpGraphicsPort(gc, dc.port);
+ dc.penPat = penPat;
+ penPat = savePat;
+ dc.saveClip = NewRgn();
+ GetPortClipRegion(dc.port, dc.saveClip);
+ if (dc.clipRgn) {
+ ChkErr(HIShapeSetQDClip, dc.clipRgn, dc.port);
+ } else {
+ NoQDClip(dc.port);
+ }
+ if (!tkPictureIsOpen) {
+ ShowPen();
+ }
+ }
+end:
+ *dcPtr = dc;
+ return !dontDraw;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXRestoreDrawingContext --
+ *
+ * Restore drawing context.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXRestoreDrawingContext(
+ TkMacOSXDrawingContext *dcPtr)
+{
+ if (dcPtr->context) {
+ CGContextSynchronize(dcPtr->context);
+ if (dcPtr->saveState) {
+ CGContextRestoreGState(dcPtr->context);
+ }
+ if (dcPtr->port) {
+ ChkErr(QDEndCGContext, dcPtr->port, &(dcPtr->context));
+ }
+ } else if (dcPtr->port) {
+ if (!tkPictureIsOpen) {
+ HidePen();
+ }
+ PenNormal();
+ if (dcPtr->saveClip) {
+ SetPortClipRegion(dcPtr->port, dcPtr->saveClip);
+ DisposeRgn(dcPtr->saveClip);
+ }
+ if (dcPtr->penPat) {
+ if (!tmpPixPat) {
+ tmpPixPat = dcPtr->penPat;
+ } else {
+ DisposePixPat(dcPtr->penPat);
+ }
+ }
+ if (dcPtr->saveState) {
+ ChkErr(SetThemeDrawingState, dcPtr->saveState, true);
+ }
+ }
+ if (dcPtr->clipRgn) {
+ CFRelease(dcPtr->clipRgn);
+ }
+ if (dcPtr->portChanged) {
+ QDSwapPort(dcPtr->savePort, NULL);
+ }
+#ifdef TK_MAC_DEBUG
+ bzero(dcPtr, sizeof(TkMacOSXDrawingContext));
+#endif /* TK_MAC_DEBUG */
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetClipRgn --
+ *
+ * Get the clipping region needed to restrict drawing to the given
+ * drawable.
+ *
+ * Results:
+ * Clipping region. If non-NULL, CFRelease it when done.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+HIShapeRef
+TkMacOSXGetClipRgn(
+ Drawable drawable) /* Drawable. */
+{
+ MacDrawable *macDraw = (MacDrawable *) drawable;
+ HIShapeRef clipRgn = NULL;
+ CGRect r;
+
+ if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) {
+ TkMacOSXUpdateClipRgn(macDraw->winPtr);
+#ifdef TK_MAC_DEBUG_DRAWING
+ TkMacOSXDbgMsg("%s visRgn ", macDraw->winPtr->pathName);
+ TkMacOSXDebugFlashRegion(drawable, macDraw->visRgn);
+#endif /* TK_MAC_DEBUG_DRAWING */
+ }
+
+ if (macDraw->flags & TK_CLIPPED_DRAW) {
+ r = CGRectOffset(macDraw->drawRect, macDraw->xOff, macDraw->yOff);
+ }
+ if (macDraw->visRgn) {
+ if (macDraw->flags & TK_CLIPPED_DRAW) {
+ HIShapeRef rgn = HIShapeCreateWithRect(&r);
+
+ clipRgn = HIShapeCreateIntersection(macDraw->visRgn, rgn);
+ CFRelease(rgn);
+ } else {
+ clipRgn = HIShapeCreateCopy(macDraw->visRgn);
+ }
+ } else if (macDraw->flags & TK_CLIPPED_DRAW) {
+ clipRgn = HIShapeCreateWithRect(&r);
+ }
+#ifdef TK_MAC_DEBUG_DRAWING
+ TkMacOSXDbgMsg("%s clipRgn ", macDraw->winPtr->pathName);
+ TkMacOSXDebugFlashRegion(drawable, clipRgn);
+#endif /* TK_MAC_DEBUG_DRAWING */
+
+ return clipRgn;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXSetUpClippingRgn --
+ *
+ * Set up the clipping region so that drawing only occurs on the
+ * specified X subwindow.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The clipping region in the current port is changed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXSetUpClippingRgn(
+ Drawable drawable) /* Drawable to update. */
+{
+ CGrafPtr port = TkMacOSXGetDrawablePort(drawable);
+
+ if (port) {
+ HIShapeRef clipRgn = TkMacOSXGetClipRgn(drawable);
+
+ if (clipRgn) {
+ ChkErr(HIShapeSetQDClip, clipRgn, port);
+ CFRelease(clipRgn);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpClipDrawableToRect --
+ *
+ * Clip all drawing into the drawable d to the given rectangle.
+ * If width and height are negative, reset to no clipping.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Subsequent drawing into d is offset and clipped as specified.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpClipDrawableToRect(
+ Display *display,
+ Drawable d,
+ int x, int y,
+ int width, int height)
+{
+ MacDrawable *macDraw = (MacDrawable *) d;
+
+ if (width < 0 && height < 0) {
+ macDraw->drawRect = CGRectNull;
+ macDraw->flags &= ~TK_CLIPPED_DRAW;
+ } else {
+ macDraw->drawRect = CGRectMake(x, y, width, height);
+ macDraw->flags |= TK_CLIPPED_DRAW;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ClipToGC --
+ *
+ * Helper function to intersect given region with gc clip region.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+ClipToGC(
+ Drawable d,
+ GC gc,
+ HIShapeRef *clipRgnPtr) /* must point to initialized variable */
+{
+ if (gc && gc->clip_mask &&
+ ((TkpClipMask*)gc->clip_mask)->type == TKP_CLIP_REGION) {
+ TkRegion gcClip = ((TkpClipMask*)gc->clip_mask)->value.region;
+ int xOffset = ((MacDrawable *) d)->xOff + gc->clip_x_origin;
+ int yOffset = ((MacDrawable *) d)->yOff + gc->clip_y_origin;
+ HIShapeRef clipRgn = *clipRgnPtr, gcClipRgn;
+
+ if (!tkPictureIsOpen) {
+ TkMacOSXOffsetRegion(gcClip, xOffset, yOffset);
+ }
+ gcClipRgn = TkMacOSXGetNativeRegion(gcClip);
+ if (clipRgn) {
+ *clipRgnPtr = HIShapeCreateIntersection(gcClipRgn, clipRgn);
+ CFRelease(clipRgn);
+ } else {
+ *clipRgnPtr = HIShapeCreateCopy(gcClipRgn);
+ }
+ CFRelease(gcClipRgn);
+ if (!tkPictureIsOpen) {
+ TkMacOSXOffsetRegion(gcClip, -xOffset, -yOffset);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * NoQDClip --
+ *
+ * Helper function to setup a QD port to not clip anything.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+NoQDClip(
+ CGrafPtr port)
+{
+ static RgnHandle noClipRgn = NULL;
+
+ if (!noClipRgn) {
+ noClipRgn = NewRgn();
+ SetRectRgn(noClipRgn, SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX);
+ }
+ SetPortClipRegion(port, noClipRgn);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXMakeStippleMap --
+ *
+ * Given a drawable and a stipple pattern this function draws the
+ * pattern repeatedly over the drawable. The drawable can then
+ * be used as a mask for bit-bliting a stipple pattern over an
+ * object.
+ *
+ * Results:
+ * A BitMap data structure.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void *
+TkMacOSXMakeStippleMap(
+ Drawable drawable, /* Window to apply stipple. */
+ Drawable stipple) /* The stipple pattern. */
+{
+ CGrafPtr stipplePort;
+ BitMapPtr bitmapPtr;
+ const BitMap *stippleBitmap;
+ Rect portRect;
+ int width, height, stippleHeight, stippleWidth, i, j;
+ Rect bounds;
+
+ GetPortBounds(TkMacOSXGetDrawablePort(drawable), &portRect);
+ width = portRect.right - portRect.left;
+ height = portRect.bottom - portRect.top;
+ bitmapPtr = ckalloc(sizeof(BitMap));
+ bitmapPtr->bounds.top = bitmapPtr->bounds.left = 0;
+ bitmapPtr->bounds.right = (short) width;
+ bitmapPtr->bounds.bottom = (short) height;
+ bitmapPtr->rowBytes = (width / 8) + 1;
+ bitmapPtr->baseAddr = ckalloc(height * bitmapPtr->rowBytes);
+
+ stipplePort = TkMacOSXGetDrawablePort(stipple);
+ stippleBitmap = GetPortBitMapForCopyBits(stipplePort);
+ GetPortBounds(stipplePort, &portRect);
+ stippleWidth = portRect.right - portRect.left;
+ stippleHeight = portRect.bottom - portRect.top;
+
+ for (i = 0; i < height; i += stippleHeight) {
+ for (j = 0; j < width; j += stippleWidth) {
+ bounds.left = j;
+ bounds.top = i;
+ bounds.right = j + stippleWidth;
+ bounds.bottom = i + stippleHeight;
+ CopyBits(stippleBitmap, bitmapPtr, &portRect, &bounds, srcCopy,
+ NULL);
+ }
+ }
+ return bitmapPtr;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDrawHighlightBorder --
+ *
+ * This procedure draws a rectangular ring around the outside of
+ * a widget to indicate that it has received the input focus.
+ *
+ * On the Macintosh, this puts a 1 pixel border in the bgGC color
+ * between the widget and the focus ring, except in the case where
+ * highlightWidth is 1, in which case the border is left out.
+ *
+ * For proper Mac L&F, use highlightWidth of 3.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * A rectangle "width" pixels wide is drawn in "drawable",
+ * corresponding to the outer area of "tkwin".
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDrawHighlightBorder (
+ Tk_Window tkwin,
+ GC fgGC,
+ GC bgGC,
+ int highlightWidth,
+ Drawable drawable)
+{
+ if (highlightWidth == 1) {
+ TkDrawInsetFocusHighlight (tkwin, fgGC, highlightWidth, drawable, 0);
+ } else {
+ TkDrawInsetFocusHighlight (tkwin, bgGC, highlightWidth, drawable, 0);
+ if (fgGC != bgGC) {
+ TkDrawInsetFocusHighlight (tkwin, fgGC, highlightWidth - 1,
+ drawable, 0);
+ }
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpDrawFrame --
+ *
+ * This procedure draws the rectangular frame area. If the user
+ * has request themeing, it draws with a the background theme.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Draws inside the tkwin area.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpDrawFrame(
+ Tk_Window tkwin,
+ Tk_3DBorder border,
+ int highlightWidth,
+ int borderWidth,
+ int relief)
+{
+ if (useThemedToplevel && Tk_IsTopLevel(tkwin)) {
+ static Tk_3DBorder themedBorder = NULL;
+
+ if (!themedBorder) {
+ themedBorder = Tk_Get3DBorder(NULL, tkwin,
+ "systemWindowHeaderBackground");
+ }
+ if (themedBorder) {
+ border = themedBorder;
+ }
+ }
+ Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin),
+ border, highlightWidth, highlightWidth,
+ Tk_Width(tkwin) - 2 * highlightWidth,
+ Tk_Height(tkwin) - 2 * highlightWidth,
+ borderWidth, relief);
+}