diff options
author | culler <culler> | 2021-04-28 05:26:46 (GMT) |
---|---|---|
committer | culler <culler> | 2021-04-28 05:26:46 (GMT) |
commit | 2ce4830f8b177a13e360b787bba7b2b73adb8183 (patch) | |
tree | a734886cbd761ecf745bbe45cc63ae447737c80a /macosx | |
parent | 3518f5614a393f2761dc58f4baa386115cbda33d (diff) | |
parent | 0512da3facc4560d40d97a359c4a1ecefbee4da5 (diff) | |
download | tk-2ce4830f8b177a13e360b787bba7b2b73adb8183.zip tk-2ce4830f8b177a13e360b787bba7b2b73adb8183.tar.gz tk-2ce4830f8b177a13e360b787bba7b2b73adb8183.tar.bz2 |
CALayer backing for 8.7
Diffstat (limited to 'macosx')
-rw-r--r-- | macosx/tkMacOSXDraw.c | 61 | ||||
-rw-r--r-- | macosx/tkMacOSXFont.c | 2 | ||||
-rw-r--r-- | macosx/tkMacOSXImage.c | 73 | ||||
-rw-r--r-- | macosx/tkMacOSXNotify.c | 7 | ||||
-rw-r--r-- | macosx/tkMacOSXPrivate.h | 2 | ||||
-rw-r--r-- | macosx/tkMacOSXRegion.c | 2 | ||||
-rw-r--r-- | macosx/tkMacOSXSubwindows.c | 6 | ||||
-rw-r--r-- | macosx/tkMacOSXWindowEvent.c | 34 | ||||
-rw-r--r-- | macosx/tkMacOSXWm.c | 9 |
9 files changed, 130 insertions, 66 deletions
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 6ef964c..9f6966a 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -27,6 +27,7 @@ #ifdef TK_MAC_DEBUG #define TK_MAC_DEBUG_DRAWING #define TK_MAC_DEBUG_IMAGE_DRAWING +#define TK_MAC_DEBUG_CG #endif */ @@ -1242,6 +1243,12 @@ TkMacOSXSetupDrawingContext( Bool canDraw = true; TKContentView *view = nil; TkMacOSXDrawingContext dc = {}; + CGFloat drawingHeight; + +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "TkMacOSXSetupDrawingContext: %s\n", + macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : "None"); +#endif /* * If the drawable is not a pixmap, get the associated NSView. @@ -1273,13 +1280,10 @@ TkMacOSXSetupDrawingContext( */ dc.context = TkMacOSXGetCGContextForDrawable(d); - if (dc.context) { - dc.portBounds = CGContextGetClipBoundingBox(dc.context); - } else { + if (!dc.context) { NSRect drawingBounds, currentBounds; dc.view = view; dc.context = GET_CGCONTEXT; - dc.portBounds = NSRectToCGRect([view bounds]); if (dc.clipRgn) { CGRect clipBounds; CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0, @@ -1331,18 +1335,22 @@ TkMacOSXSetupDrawingContext( * Finish configuring the drawing context. */ +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "TkMacOSXSetupDrawingContext: pushing GState for %s\n", + macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : "None"); +#endif + + CGContextSaveGState(dc.context); + CGContextSetTextDrawingMode(dc.context, kCGTextFill); { /* Restricted scope for t needed for C++ */ + drawingHeight = view ? [view bounds].size.height : + CGContextGetClipBoundingBox(dc.context).size.height; CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0, - .ty = dc.portBounds.size.height + .ty = drawingHeight }; - - dc.portBounds.origin.x += macDraw->xOff; - dc.portBounds.origin.y += macDraw->yOff; - CGContextSaveGState(dc.context); - CGContextSetTextDrawingMode(dc.context, kCGTextFill); CGContextConcatCTM(dc.context, t); } if (dc.clipRgn) { @@ -1367,11 +1375,26 @@ TkMacOSXSetupDrawingContext( */ ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context); + +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "Setting complex clip for %s to:\n", + macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : "None"); + TkMacOSXPrintRectsInRegion(dc.clipRgn); +#endif + CGContextEOClip(dc.context); - } - else { + } else { CGRect r; HIShapeGetBounds(dc.clipRgn, &r); + +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "Current clip BBox is %s\n", + NSStringFromRect(CGContextGetClipBoundingBox(GET_CGCONTEXT)).UTF8String); + fprintf(stderr, "Setting clip for %s to rect %s:\n", + macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : "None", + NSStringFromRect(r).UTF8String); +#endif + CGContextClipToRect(dc.context, r); } } @@ -1392,8 +1415,8 @@ TkMacOSXSetupDrawingContext( TkMacOSXSetColorInContext(gc, gc->foreground, dc.context); if (view) { - CGContextSetPatternPhase(dc.context, - CGSizeMake(dc.portBounds.size.width, dc.portBounds.size.height)); + CGSize size = NSSizeToCGSize([view bounds].size); + CGContextSetPatternPhase(dc.context, size); } if (gc->function != GXcopy) { TkMacOSXDbgMsg("Logical functions other than GXcopy are " @@ -1470,13 +1493,21 @@ TkMacOSXRestoreDrawingContext( if (dcPtr->context) { CGContextSynchronize(dcPtr->context); CGContextRestoreGState(dcPtr->context); + +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "TkMacOSXRestoreDrawingContext: popped GState\n"); +#endif + } if (dcPtr->clipRgn) { CFRelease(dcPtr->clipRgn); + dcPtr->clipRgn = NULL; } + #ifdef TK_MAC_DEBUG bzero(dcPtr, sizeof(TkMacOSXDrawingContext)); -#endif /* TK_MAC_DEBUG */ +#endif + } /* diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index ab13fd0..496dc35 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -1220,7 +1220,7 @@ TkpDrawAngledCharsInContext( (CFAttributedStringRef)attributedString); textX += (CGFloat) macWin->xOff; textY += (CGFloat) macWin->yOff; - height = drawingContext.portBounds.size.height; + height = [drawingContext.view bounds].size.height; textY = height - textY; t = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, height); if (angle != 0.0) { diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c index 47e3b70..17a0df1 100644 --- a/macosx/tkMacOSXImage.c +++ b/macosx/tkMacOSXImage.c @@ -515,51 +515,42 @@ CreateCGImageFromDrawableRect( { MacDrawable *mac_drawable = (MacDrawable *)drawable; CGContextRef cg_context = NULL; + CGRect image_rect = CGRectMake(x, y, width, height); CGImageRef cg_image = NULL, result = NULL; - NSBitmapImageRep *bitmapRep = nil; - NSView *view = nil; + unsigned char *imageData = NULL; if (mac_drawable->flags & TK_IS_PIXMAP) { - /* - * This MacDrawable is a bitmap, so its view is NULL. - */ - - CGRect image_rect = CGRectMake(x, y, width, height); - cg_context = TkMacOSXGetCGContextForDrawable(drawable); - cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context); - if (cg_image) { - result = CGImageCreateWithImageInRect(cg_image, image_rect); - CGImageRelease(cg_image); - } - } else if (TkMacOSXGetNSViewForDrawable(mac_drawable) != nil) { - - /* - * Convert Tk top-left to NSView bottom-left coordinates. - */ - - int view_height = [view bounds].size.height; - NSRect view_rect = NSMakeRect(x + mac_drawable->xOff, - view_height - height - y - mac_drawable->yOff, - width, height); - - /* - * Attempt to copy from the view to a bitmapImageRep. If the view does - * not have a valid CGContext, doing this will silently corrupt memory - * and make a big mess. So, in that case, we just return NULL. - */ - - if (view == [NSView focusView]) { - bitmapRep = [view bitmapImageRepForCachingDisplayInRect: view_rect]; - [view cacheDisplayInRect:view_rect toBitmapImageRep:bitmapRep]; - result = [bitmapRep CGImage]; - CFRelease(bitmapRep); - } else { - TkMacOSXDbgMsg("No CGContext - cannot copy from screen to bitmap."); - result = NULL; + if (cg_context) { + cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context); } } else { - TkMacOSXDbgMsg("Invalid source drawable"); + NSView *view = TkMacOSXGetNSViewForDrawable(mac_drawable); + if (view == nil) { + TkMacOSXDbgMsg("Invalid source drawable"); + return NULL; + } + NSSize size = view.frame.size; + NSUInteger width = size.width, height = size.height; + NSUInteger bytesPerPixel = 4, + bytesPerRow = bytesPerPixel * width, + bitsPerComponent = 8; + imageData = ckalloc(height * bytesPerRow); + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + cg_context = CGBitmapContextCreate(imageData, width, height, + bitsPerComponent, bytesPerRow, colorSpace, + kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); + CFRelease(colorSpace); + [view.layer renderInContext:cg_context]; + } + if (cg_context) { + cg_image = CGBitmapContextCreateImage(cg_context); + CGContextRelease(cg_context); + } + if (cg_image) { + result = CGImageCreateWithImageInRect(cg_image, image_rect); + CGImageRelease(cg_image); } + ckfree(imageData); return result; } @@ -663,11 +654,11 @@ XGetImage( || bytes_per_row < 4 * width || size != bytes_per_row * height) { TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format"); - CFRelease(bitmapRep); + [bitmapRep release]; return NULL; } memcpy(bitmap, (char *)[bitmapRep bitmapData], size); - CFRelease(bitmapRep); + [bitmapRep release]; /* * When Apple extracts a bitmap from an NSView, it may be in either diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c index 1e78521..46496da 100644 --- a/macosx/tkMacOSXNotify.c +++ b/macosx/tkMacOSXNotify.c @@ -343,8 +343,9 @@ TkMacOSXNotifyExitHandler( * for all views that need display before it returns. We call it with * deQueue=NO so that it will not change anything on the AppKit event * queue, because we only want the side effect that it runs drawRect. The - * only time when any NSViews have the needsDisplay property set to YES - * is during execution of this function. + * only times when any NSViews have the needsDisplay property set to YES + * are during execution of this function or in the addDirtyRect method + * of TKContentView. * * The reason for running this function as an idle task is to try to * arrange that all widgets will be fully configured before they are @@ -380,7 +381,7 @@ TkMacOSXDrawAllViews( if (dirtyCount) { continue; } - [view setNeedsDisplayInRect:[view tkDirtyRect]]; + [[view layer] setNeedsDisplayInRect:[view tkDirtyRect]]; } } else { [window displayIfNeeded]; diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 5936eed..33df1d8 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -29,6 +29,7 @@ #import <ApplicationServices/ApplicationServices.h> #undef Cursor #import <Cocoa/Cocoa.h> +#import <QuartzCore/QuartzCore.h> #ifndef NO_CARBON_H #import <Carbon/Carbon.h> #endif @@ -206,7 +207,6 @@ typedef struct TkMacOSXDrawingContext { CGContextRef context; NSView *view; HIShapeRef clipRgn; - CGRect portBounds; } TkMacOSXDrawingContext; /* diff --git a/macosx/tkMacOSXRegion.c b/macosx/tkMacOSXRegion.c index 39f6821..b44073a 100644 --- a/macosx/tkMacOSXRegion.c +++ b/macosx/tkMacOSXRegion.c @@ -575,7 +575,7 @@ rectPrinter( TCL_UNUSED(void *)) { if (rect) { - printf(" %s\n", NSStringFromRect(*rect).UTF8String); + fprintf(stderr, " %s\n", NSStringFromRect(*rect).UTF8String); } return noErr; } diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c index 690b9fc..d9603d7 100644 --- a/macosx/tkMacOSXSubwindows.c +++ b/macosx/tkMacOSXSubwindows.c @@ -1440,7 +1440,11 @@ Tk_FreePixmap( if (data) { ckfree(data); } - CFRelease(macPix->context); + /* + * Releasing the context here causes a crash in the 8.7 regression + * tests, but not in 8.6. + * CFRelease(macPix->context); + */ } ckfree(macPix); } diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c index d6923db..3305bd3 100644 --- a/macosx/tkMacOSXWindowEvent.c +++ b/macosx/tkMacOSXWindowEvent.c @@ -915,11 +915,45 @@ ConfigureRestrictProc( @implementation TKContentView(TKWindowEvent) +- (id)initWithFrame:(NSRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + /* + * The layer must exist before we set wantsLayer to YES. + */ + + self.layer = [CALayer layer]; + self.wantsLayer = YES; + self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay; + self.layer.contentsGravity = self.layer.contentsAreFlipped ? + kCAGravityTopLeft : kCAGravityBottomLeft; + + /* + * Nothing gets drawn at all if the layer does not have a delegate. + * Currently, we do not implement any methods of the delegate, however. + */ + + self.layer.delegate = (id) self; + } + return self; +} + +/* + * We will just use drawRect. + */ + +- (BOOL) wantsUpdateLayer +{ + return NO; +} + - (void) addTkDirtyRect: (NSRect) rect { _tkNeedsDisplay = YES; _tkDirtyRect = NSUnionRect(_tkDirtyRect, rect); [NSApp setNeedsToDraw:YES]; + [self setNeedsDisplay:YES]; } - (void) clearTkDirtyRect diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index aea25e4..7a40135 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -5516,12 +5516,15 @@ Tk_MacOSXGetTkWindow( void *w) { Window window = None; - TkDisplay *dispPtr = TkGetDisplayList(); if ([(NSWindow *)w respondsToSelector: @selector (tkWindow)]) { window = [(TKWindow *)w tkWindow]; } - return (window != None ? - Tk_IdToWindow(dispPtr->display, window) : NULL); + if (window) { + TkDisplay *dispPtr = TkGetDisplayList(); + return Tk_IdToWindow(dispPtr->display, window); + } else { + return NULL; + } } /* |