diff options
Diffstat (limited to 'macosx/tkMacOSXDraw.c')
-rw-r--r-- | macosx/tkMacOSXDraw.c | 660 |
1 files changed, 396 insertions, 264 deletions
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 8960567..5d1157c 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.2.2.29 2007/07/09 08:30:31 das Exp $ + * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.2.2.30 2007/11/09 06:26:55 das Exp $ */ #include "tkMacOSXPrivate.h" @@ -43,6 +43,8 @@ RgnHandle tkMacOSXtmpQdRgn = NULL; int tkMacOSXUseCGDrawing = 1; +int tkPictureIsOpen; + static PixPatHandle penPat = NULL; static int cgAntiAliasLimit = 0; @@ -55,7 +57,7 @@ static int useThemedFrame = 0; * Prototypes for functions used only in this file. */ -static void ClipToGC(Drawable d, GC gc, CGrafPtr port, RgnHandle clipRgn); +static void ClipToGC(Drawable d, GC gc, HIShapeRef *clipRgnPtr); static void NoQDClip(CGrafPtr port); @@ -153,7 +155,7 @@ XCopyArea( GC gc, /* GC to use. */ int src_x, /* X & Y, width & height */ int src_y, /* define the source rectangle */ - unsigned int width, /* the will be copied. */ + unsigned int width, /* that will be copied. */ unsigned int height, int dest_x, /* Dest X & Y on dest rect. */ int dest_y) @@ -163,32 +165,50 @@ XCopyArea( display->request++; if (!width || !height) { - TkMacOSXDbgMsg("Drawing of emtpy area requested"); + /* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */ return; } - if (!TkMacOSXSetupDrawingContext(dst, gc, 0, &dc)) { - Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect; + { CGrafPtr srcPort; - const BitMap *srcBit, *dstBit; - RGBColor black = {0, 0, 0}, white = {0xffff, 0xffff, 0xffff}; srcPort = TkMacOSXGetDrawablePort(src); - 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; + 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 { - SetRect(dstPtr, dstDraw->xOff + dest_x, dstDraw->yOff + dest_y, - dstDraw->xOff + dest_x + width, - dstDraw->yOff + dest_y + height); + TkMacOSXDbgMsg("Invalid source drawable"); } - RGBForeColor(&black); - RGBBackColor(&white); - CopyBits(srcBit, dstBit, srcPtr, dstPtr, srcCopy, NULL); } - TkMacOSXRestoreDrawingContext(&dc); } /* @@ -218,7 +238,7 @@ XCopyPlane( GC gc, /* GC to use. */ int src_x, /* X & Y, width & height */ int src_y, /* define the source rectangle */ - unsigned int width, /* the will be copied. */ + unsigned int width, /* that will be copied. */ unsigned int height, int dest_x, /* Dest X & Y on dest rect. */ int dest_y, @@ -229,61 +249,80 @@ XCopyPlane( display->request++; if (!width || !height) { - TkMacOSXDbgMsg("Drawing of emtpy area requested"); + /* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */ return; } if (plane != 1) { Tcl_Panic("Unexpected plane specified for XCopyPlane"); } - if (!TkMacOSXSetupDrawingContext(dst, gc, 0, &dc)) { - Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect; + { CGrafPtr srcPort; - const BitMap *srcBit, *dstBit; - TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask; srcPort = TkMacOSXGetDrawablePort(src); - 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. - */ + if (srcPort) { + Rect srcRect, dstRect, *srcPtr = &srcRect, *dstPtr = &dstRect; + const BitMap *srcBit, *dstBit; + TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask; - 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 we ignore the forecolor. - */ - short tmode = GetPixDepth(GetPortPixMap(srcPort)) == 1 ? - srcOr : transparent; - - CopyBits(srcBit, dstBit, srcPtr, dstPtr, tmode, NULL); + 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) { /* - * Two arbitrary bitmaps. + * Opaque bitmaps. */ - CGrafPtr mskPort = TkMacOSXGetDrawablePort(clipPtr->value.pixmap); - const BitMap *mskBit = GetPortBitMapForCopyBits(mskPort); + 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); + CopyDeepMask(srcBit, mskBit, dstBit, srcPtr, srcPtr, + dstPtr, srcCopy, NULL); + } } +end: + TkMacOSXRestoreDrawingContext(&dc); + } else { + TkMacOSXDbgMsg("Invalid source drawable"); } } - TkMacOSXRestoreDrawingContext(&dc); } /* @@ -323,14 +362,19 @@ TkPutImage( 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; - int slices, sliceRowBytes, lastSliceRowBytes, sliceWidth, lastSliceWidth; + 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); @@ -348,8 +392,9 @@ TkPutImage( * Image from XGetImage, copy from containing GWorld directly. */ - CopyBits(GetPortBitMapForCopyBits(TkMacOSXGetDrawablePort((Drawable) - image->obdata)), dstBit, srcPtr, dstPtr, srcCopy, NULL); + CopyBits(GetPortBitMapForCopyBits(TkMacOSXGetDrawablePort( + (Drawable)image->obdata)), dstBit, + srcPtr, dstPtr, srcCopy, NULL); } else if (image->depth == 1) { /* * BW image @@ -529,7 +574,10 @@ XDrawLines( } display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { double prevx, prevy; double o = (lw % 2) ? .5 : 0; @@ -599,7 +647,10 @@ XDrawSegments( int i, lw = gc->line_width; display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { double o = (lw % 2) ? .5 : 0; for (i = 0; i < nsegments; i++) { @@ -660,7 +711,10 @@ XFillPolygon( int i; display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { double prevx, prevy; double o = (gc->line_width % 2) ? .5 : 0; @@ -735,7 +789,10 @@ XDrawRectangle( } display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0; @@ -798,7 +855,10 @@ XDrawRectangles( int i, lw = gc->line_width; display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0; @@ -858,7 +918,10 @@ XFillRectangles( int i; display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; for (i = 0, rectPtr = rectangles; i < n_rectangles; i++, rectPtr++) { @@ -921,7 +984,10 @@ XDrawArc( } display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0; @@ -1003,7 +1069,10 @@ XDrawArcs( int i, lw = gc->line_width; display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0; @@ -1096,7 +1165,10 @@ XFillArc( } display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0, u = 0; @@ -1210,7 +1282,10 @@ XFillArcs( int i, lw = gc->line_width; display->request++; - if (TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + if (!TkMacOSXSetupDrawingContext(d, gc, tkMacOSXUseCGDrawing, &dc)) { + return; + } + if (dc.context) { CGRect rect; double o = (lw % 2) ? .5 : 0, u = 0; @@ -1356,7 +1431,7 @@ TkScrollWindow( Boolean portChanged; Rect scrollRect; int result; - RgnHandle rgn = (RgnHandle) damageRgn; + HIShapeRef dmgRgn; /* * Due to the implementation below the behavior may be differnt @@ -1385,8 +1460,9 @@ TkScrollWindow( destPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin)); TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); + TkMacOSXCheckTmpQdRgnEmpty(); portChanged = QDSwapPort(destPort, &savePort); - ScrollRect(&scrollRect, dx, dy, rgn); + ScrollRect(&scrollRect, dx, dy, tkMacOSXtmpQdRgn); if (portChanged) { QDSwapPort(savePort, NULL); } @@ -1398,7 +1474,11 @@ TkScrollWindow( * created. */ - result = EmptyRgn(rgn) ? 0 : 1; + dmgRgn = HIShapeCreateWithQDRgn(tkMacOSXtmpQdRgn); + SetEmptyRgn(tkMacOSXtmpQdRgn); + TkMacOSXSetWithNativeRegion(damageRgn, dmgRgn); + result = HIShapeIsEmpty(dmgRgn) ? 0 : 1; + CFRelease(dmgRgn); return result; } @@ -1456,7 +1536,9 @@ TkMacOSXSetUpGraphicsPort( * Set up a drawing context for the given drawable and GC. * * Results: - * Boolean indicating whether to use CG drawing. + * 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. @@ -1469,149 +1551,160 @@ TkMacOSXSetupDrawingContext( Drawable d, GC gc, int useCG, /* advisory only ! */ - TkMacOSXDrawingContext *dc) + TkMacOSXDrawingContext *dcPtr) { MacDrawable *macDraw = ((MacDrawable*)d); - CGContextRef context = macDraw->context; - CGrafPtr port; - Rect portBounds; - - dc->saveState = NULL; - dc->saveClip = NULL; - dc->penPat = NULL; - dc->portChanged = false; - port = TkMacOSXGetDrawablePort(d); - if (port) { - GetPortBounds(port, &portBounds); - dc->saveClip = NewRgn(); - GetPortClipRegion(port, dc->saveClip); - if (tkPictureIsOpen) { - NoQDClip(port); - } else { - TkMacOSXSetUpClippingRgn(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 (context && useCG) { - if (!port) { - TK_IF_MAC_OS_X_API (3, CGContextGetClipBoundingBox, - CGRect r = CGContextGetClipBoundingBox(context); + 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; - SetRect(&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); + 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(context); - dc->saveState = (void*)1; - port = NULL; - } else if (port) { - dc->portChanged = QDSwapPort(port, &(dc->savePort)); - if (useCG && ChkErr(QDBeginCGContext, port, &context) == noErr) { - SyncCGContextOriginWithPort(context, port); + 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 { - context = NULL; - useCG = 0; + dc.context = NULL; } } else { Tcl_Panic("TkMacOSXSetupDrawingContext(): " "no port or context to draw into !"); } - if (useCG) { - if (tkPictureIsOpen) { - TkMacOSXDbgMsg("Ignored CG Drawing with QD Picture open"); - } else if (context) { - TkMacOSXCheckTmpQdRgnEmpty(); - RectRgn(tkMacOSXtmpQdRgn, &portBounds); - if (port) { - SectRegionWithPortClipRegion(port, tkMacOSXtmpQdRgn); - SectRegionWithPortVisibleRegion(port, tkMacOSXtmpQdRgn); - } else if (macDraw->flags & TK_CLIPPED_DRAW) { - OffsetRgn(macDraw->drawRgn, macDraw->xOff, macDraw->yOff); - SectRgn(macDraw->clipRgn, macDraw->drawRgn, tkMacOSXtmpQdRgn); - OffsetRgn(macDraw->drawRgn, -macDraw->xOff, -macDraw->yOff); + 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)); } - ClipToGC(d, gc, NULL, tkMacOSXtmpQdRgn); - ClipCGContextToRegion(context, &portBounds, tkMacOSXtmpQdRgn); - SetEmptyRgn(tkMacOSXtmpQdRgn); - CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0, - -1.0, 0.0, portBounds.bottom - portBounds.top)); - if (gc) { - double w = gc->line_width; - - TkMacOSXSetColorInContext(gc->foreground, context); - if (port) { - CGContextSetPatternPhase(context, - CGSizeMake(portBounds.right - portBounds.left, - portBounds.bottom - portBounds.top)); - } - if(gc->function != GXcopy) { - TkMacOSXDbgMsg("Logical functions other than GXcopy are " - "not supported for CG drawing!"); - } - /* When should we antialias? */ - if (notAA(gc->line_width)) { - /* Make non-antialiased CG drawing look more like X11 */ - w -= (gc->line_width ? NON_AA_CG_OFFSET : 0); - CGContextSetShouldAntialias(context, 0); - } else { - CGContextSetShouldAntialias(context, 1); - } - CGContextSetLineWidth(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(context, dashOffset, lengths, num); - } - if (gc->cap_style == CapButt) { - /* - * What about CapNotLast, CapProjecting? - */ - - CGContextSetLineCap(context, kCGLineCapButt); - } else if (gc->cap_style == CapRound) { - CGContextSetLineCap(context, kCGLineCapRound); - } else if (gc->cap_style == CapProjecting) { - CGContextSetLineCap(context, kCGLineCapSquare); - } - if (gc->join_style == JoinMiter) { - CGContextSetLineJoin(context, kCGLineJoinMiter); - } else if (gc->join_style == JoinRound) { - CGContextSetLineJoin(context, kCGLineJoinRound); - } else if (gc->join_style == JoinBevel) { - CGContextSetLineJoin(context, kCGLineJoinBevel); + 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); } - } - } else { - if (port) { - PixPatHandle savePat = penPat; - - ChkErr(GetThemeDrawingState, &(dc->saveState)); - penPat = NULL; - TkMacOSXSetUpGraphicsPort(gc, port); - dc->penPat = penPat; - penPat = savePat; - if (gc) { - TkMacOSXCheckTmpQdRgnEmpty(); - ClipToGC(d, gc, port, tkMacOSXtmpQdRgn); + if ((unsigned)gc->cap_style < sizeof(cgCap)/sizeof(CGLineCap)) { + CGContextSetLineCap(dc.context, + cgCap[(unsigned)gc->cap_style]); } - if (!tkPictureIsOpen) { - ShowPen(); + 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(); + } } - dc->portBounds = portBounds; - dc->port = port; - dc->context = context; - return useCG; +end: + *dcPtr = dc; + return !dontDraw; } /* @@ -1631,87 +1724,130 @@ TkMacOSXSetupDrawingContext( */ void -TkMacOSXRestoreDrawingContext(TkMacOSXDrawingContext *dc) +TkMacOSXRestoreDrawingContext( + TkMacOSXDrawingContext *dcPtr) { - if (dc->context) { - CGContextSynchronize(dc->context); - if (dc->saveState) { - CGContextRestoreGState(dc->context); + if (dcPtr->context) { + CGContextSynchronize(dcPtr->context); + if (dcPtr->saveState) { + CGContextRestoreGState(dcPtr->context); } - if (dc->port) { - ChkErr(QDEndCGContext, dc->port, &(dc->context)); + if (dcPtr->port) { + ChkErr(QDEndCGContext, dcPtr->port, &(dcPtr->context)); } - } else if (dc->port) { + } else if (dcPtr->port) { if (!tkPictureIsOpen) { HidePen(); } PenNormal(); - if (dc->saveClip) { - SetPortClipRegion(dc->port, dc->saveClip); - DisposeRgn(dc->saveClip); + if (dcPtr->saveClip) { + SetPortClipRegion(dcPtr->port, dcPtr->saveClip); + DisposeRgn(dcPtr->saveClip); } - if (dc->penPat) { - DisposePixPat(dc->penPat); + if (dcPtr->penPat) { + DisposePixPat(dcPtr->penPat); } - if (dc->saveState) { - ChkErr(SetThemeDrawingState, dc->saveState, true); + if (dcPtr->saveState) { + ChkErr(SetThemeDrawingState, dcPtr->saveState, true); } } - if (dc->portChanged) { - QDSwapPort(dc->savePort, NULL); + if (dcPtr->clipRgn) { + CFRelease(dcPtr->clipRgn); + } + if (dcPtr->portChanged) { + QDSwapPort(dcPtr->savePort, NULL); } #ifdef TK_MAC_DEBUG - bzero(dc, sizeof(dc)); + bzero(dcPtr, sizeof(dcPtr)); #endif /* TK_MAC_DEBUG */ } /* *---------------------------------------------------------------------- * - * TkMacOSXSetUpClippingRgn -- + * TkMacOSXGetClipRgn -- * - * Set up the clipping region so that drawing only occurs on the - * specified X subwindow. + * Get the clipping region needed to restrict drawing to the given + * drawable. * * Results: - * None. + * Clipping region. If non-NULL, CFRelease it when done. * * Side effects: - * The clipping region in the current port is changed. + * None. * *---------------------------------------------------------------------- */ -void -TkMacOSXSetUpClippingRgn( - Drawable drawable) /* Drawable to update. */ +HIShapeRef +TkMacOSXGetClipRgn( + Drawable drawable) /* Drawable. */ { MacDrawable *macDraw = (MacDrawable *) drawable; - CGrafPtr port = TkMacOSXGetDrawablePort(drawable); + HIShapeRef clipRgn = NULL; + CGRect r; if (macDraw->winPtr && macDraw->flags & TK_CLIP_INVALID) { TkMacOSXUpdateClipRgn(macDraw->winPtr); #ifdef TK_MAC_DEBUG_DRAWING - TkMacOSXDbgMsg("%s clipRgn ", macDraw->winPtr->pathName); - TkMacOSXDebugFlashRegion(drawable, macDraw->clipRgn); + TkMacOSXDbgMsg("%s visRgn ", macDraw->winPtr->pathName); + TkMacOSXDebugFlashRegion(drawable, macDraw->visRgn); #endif /* TK_MAC_DEBUG_DRAWING */ } - if (macDraw->clipRgn) { + if (macDraw->flags & TK_CLIPPED_DRAW) { + r = CGRectOffset(macDraw->drawRect, macDraw->xOff, macDraw->yOff); + } + if (macDraw->visRgn) { if (macDraw->flags & TK_CLIPPED_DRAW) { - TkMacOSXCheckTmpQdRgnEmpty(); - OffsetRgn(macDraw->drawRgn, macDraw->xOff, macDraw->yOff); - SectRgn(macDraw->clipRgn, macDraw->drawRgn, tkMacOSXtmpQdRgn); - OffsetRgn(macDraw->drawRgn, -macDraw->xOff, -macDraw->yOff); - SetPortClipRegion(port, tkMacOSXtmpQdRgn); - SetEmptyRgn(tkMacOSXtmpQdRgn); + HIShapeRef rgn = HIShapeCreateWithRect(&r); + + clipRgn = HIShapeCreateIntersection(macDraw->visRgn, rgn); + CFRelease(rgn); } else { - SetPortClipRegion(port, macDraw->clipRgn); + clipRgn = HIShapeCreateCopy(macDraw->visRgn); } } else if (macDraw->flags & TK_CLIPPED_DRAW) { - OffsetRgn(macDraw->drawRgn, macDraw->xOff, macDraw->yOff); - SetPortClipRegion(port, macDraw->drawRgn); - OffsetRgn(macDraw->drawRgn, -macDraw->xOff, -macDraw->yOff); + 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); + } } } @@ -1741,14 +1877,12 @@ TkpClipDrawableToRect( { MacDrawable *macDraw = (MacDrawable *) d; - if (macDraw->drawRgn) { - if (width < 0 && height < 0) { - SetEmptyRgn(macDraw->drawRgn); - macDraw->flags &= ~TK_CLIPPED_DRAW; - } else { - SetRectRgn(macDraw->drawRgn, x, y, x + width, y + height); - macDraw->flags |= TK_CLIPPED_DRAW; - } + 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; } } @@ -1757,8 +1891,7 @@ TkpClipDrawableToRect( * * ClipToGC -- * - * Helper function to intersect the given port's clip region (or if - * port is NULL, the given clipRgn) with gc clip region. + * Helper function to intersect given region with gc clip region. * * Results: * None. @@ -1773,29 +1906,28 @@ static void ClipToGC( Drawable d, GC gc, - CGrafPtr port, /* can be NULL */ - RgnHandle clipRgn) /* tmp region or if port == NULL, region to intersect */ + HIShapeRef *clipRgnPtr) /* must point to initialized variable */ { if (gc && gc->clip_mask && ((TkpClipMask*)gc->clip_mask)->type == TKP_CLIP_REGION) { - RgnHandle gcClipRgn = (RgnHandle) - ((TkpClipMask*)gc->clip_mask)->value.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) { - OffsetRgn(gcClipRgn, xOffset, yOffset); + TkMacOSXOffsetRegion(gcClip, xOffset, yOffset); } - if (port) { - GetPortClipRegion(port, clipRgn); - } - SectRgn(clipRgn, gcClipRgn, clipRgn); - if (port) { - SetPortClipRegion(port, clipRgn); - SetEmptyRgn(clipRgn); + gcClipRgn = TkMacOSXGetNativeRegion(gcClip); + if (clipRgn) { + *clipRgnPtr = HIShapeCreateIntersection(gcClipRgn, clipRgn); + CFRelease(clipRgn); + } else { + *clipRgnPtr = HIShapeCreateCopy(gcClipRgn); } + CFRelease(gcClipRgn); if (!tkPictureIsOpen) { - OffsetRgn(gcClipRgn, -xOffset, -yOffset); + TkMacOSXOffsetRegion(gcClip, -xOffset, -yOffset); } } } |