From 4df37883023ffe425f61e4b56ba5d4d3af38f7d4 Mon Sep 17 00:00:00 2001
From: Christopher Chavez <chrischavez@gmx.us>
Date: Fri, 7 Aug 2020 11:49:00 -0500
Subject: [PATCH 2/6] Aqua: remove XImage pixelpower attribute

Move backingScaleFactor wrapping to new function

See https://core.tcl-lang.org/tk/info/fcd6717d8b
---
 generic/tkImgPhInstance.c |  3 --
 macosx/tkMacOSXDraw.c     | 42 ++++++++++++++++++++++++++++
 macosx/tkMacOSXImage.c    | 58 +++++----------------------------------
 macosx/tkMacOSXPrivate.h  | 14 ++++++++++
 xlib/X11/Xlib.h           |  3 --
 5 files changed, 63 insertions(+), 57 deletions(-)

diff --git generic/tkImgPhInstance.c generic/tkImgPhInstance.c
index c5000500f..84c2adfd0 100644
--- generic/tkImgPhInstance.c
+++ generic/tkImgPhInstance.c
@@ -409,9 +409,6 @@ TkImgPhotoGet(
  *
  *	Note that Win32 pre-defines those operations that we really need.
  *
- *	Note that on MacOS, if the background comes from a Retina display
- *	then it will be twice as wide and twice as high as the photoimage.
- *
  *----------------------------------------------------------------------
  */
 #ifndef TKPUTIMAGE_CAN_BLEND
diff --git macosx/tkMacOSXDraw.c macosx/tkMacOSXDraw.c
index 59379e6c8..2e820c51b 100644
--- macosx/tkMacOSXDraw.c
+++ macosx/tkMacOSXDraw.c
@@ -210,6 +210,48 @@ TkMacOSXBitmapRepFromDrawableRect(
     return bitmap_rep;
 }
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXNSWindowBackingScaleFactor
+ *
+ *	Compatibility wrapper for NSWindow backingScaleFactor
+ *	property (present only on macOS 10.7+).
+ *
+ * Results:
+ *	Returns the backingScaleFactor for the given NSWindow,
+ *	which is currently either 2 for a window on a Retina
+ *	display, or 1 otherwise.
+ *
+ * Side effects:
+ *     None
+ *
+ *----------------------------------------------------------------------
+ */
+
+TkMacOSXNSWindowHasRetinaEnum tkMacOSXNSWindowHasRetina =
+	NSWINDOW_HAS_RETINA_UNKNOWN;
+
+int
+TkMacOSXNSWindowBackingScaleFactor(
+    NSWindow *win)
+{
+#ifdef __clang__
+    if (tkMacOSXNSWindowHasRetina == NSWINDOW_HAS_RETINA_UNKNOWN) {
+	tkMacOSXNSWindowHasRetina = [NSWindow
+		instancesRespondToSelector:@selector(backingScaleFactor)]
+		? NSWINDOW_HAS_RETINA_YES : NSWINDOW_HAS_RETINA_NO;
+    }
+    if (tkMacOSXNSWindowHasRetina == NSWINDOW_HAS_RETINA_YES) {
+	/*
+	 * We only allow scale factors of 1 or 2, as Apple currently does.
+	 */
+	return [win backingScaleFactor] == 2.0 ? 2 : 1;
+    }
+#endif
+    return 1;
+}
+
 /*
  *----------------------------------------------------------------------
  *
diff --git macosx/tkMacOSXImage.c macosx/tkMacOSXImage.c
index 3fc472e44..7a0edb346 100644
--- macosx/tkMacOSXImage.c
+++ macosx/tkMacOSXImage.c
@@ -143,8 +143,7 @@ TkMacOSXCreateCGImageWithXImage(
  * Results:
  *	Returns a newly allocated XImage containing the data from the given
  *	rectangle of the given drawable, or NULL if the XImage could not be
- *	constructed.  NOTE: If we are copying from a window on a Retina
- *	display, the dimensions of the XImage will be 2*width x 2*height.
+ *	constructed.
  *
  * Side effects:
  *	If successful, allocates an XImage.
@@ -173,30 +172,6 @@ XGetImage(
     char R, G, B, A;
     int depth = 32, offset = 0, bitmap_pad = 0;
     unsigned int bytes_per_row, size, row, n, m;
-    unsigned int scalefactor=1, scaled_height=height, scaled_width=width;
-    NSWindow *win = TkMacOSXDrawableWindow(drawable);
-    static enum {unknown, no, yes} has_retina = unknown;
-
-    if (win && has_retina == unknown) {
-#ifdef __clang__
-	has_retina = [win respondsToSelector:@selector(backingScaleFactor)] ?
-		yes : no;
-#else
-	has_retina = no;
-#endif
-    }
-
-    if (has_retina == yes) {
-	/*
-	 * We only allow scale factors 1 or 2, as Apple currently does.
-	 */
-
-#ifdef __clang__
-	scalefactor = [win backingScaleFactor] == 2.0 ? 2 : 1;
-#endif
-	scaled_height *= scalefactor;
-	scaled_width *= scalefactor;
-    }
 
     if (format == ZPixmap) {
 	if (width == 0 || height == 0) {
@@ -217,8 +192,8 @@ XGetImage(
 		|| (bitmap_fmt != 0 && bitmap_fmt != 1)
 		|| [bitmap_rep samplesPerPixel] != 4
 		|| [bitmap_rep isPlanar] != 0
-		|| bytes_per_row < 4 * scaled_width
-		|| size != bytes_per_row * scaled_height) {
+		|| bytes_per_row < 4 * width
+		|| size != bytes_per_row * height) {
 	    TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format");
 	    CFRelease(bitmap_rep);
 	    return NULL;
@@ -233,8 +208,8 @@ XGetImage(
 
 	struct pixel_fmt pixel = bitmap_fmt == 0 ? bgra : abgr;
 
-	for (row = 0, n = 0; row < scaled_height; row++, n += bytes_per_row) {
-	    for (m = n; m < n + 4*scaled_width; m += 4) {
+	for (row = 0, n = 0; row < height; row++, n += bytes_per_row) {
+	    for (m = n; m < n + 4*width; m += 4) {
 		R = *(bitmap + m + pixel.r);
 		G = *(bitmap + m + pixel.g);
 		B = *(bitmap + m + pixel.b);
@@ -247,11 +222,8 @@ XGetImage(
 	    }
 	}
 	imagePtr = XCreateImage(display, NULL, depth, format, offset,
-		(char*) bitmap, scaled_width, scaled_height,
+		(char*) bitmap, width, height,
 		bitmap_pad, bytes_per_row);
-	if (scalefactor == 2) {
-	    imagePtr->pixelpower = 1;
-	}
     } else {
 	/*
 	 * There are some calls to XGetImage in the generic Tk code which pass
@@ -473,13 +445,6 @@ XCreateImage(
     ximage->data = data;
     ximage->obdata = NULL;
 
-    /*
-     * The default pixelpower is 0.  This must be explicitly set to 1 in the
-     * case of an XImage extracted from a Retina display.
-     */
-
-    ximage->pixelpower = 0;
-
     if (format == ZPixmap) {
 	ximage->bits_per_pixel = 32;
 	ximage->bitmap_unit = 32;
@@ -574,17 +539,8 @@ XPutImage(
 	}
 	if (img) {
 
-	    /*
-	     * If the XImage has big pixels, the source is rescaled to reflect
-	     * the actual pixel dimensions.  This is not currently used, but
-	     * could arise if the image were copied from a retina monitor and
-	     * redrawn on an ordinary monitor.
-	     */
-
-	    int pp = image->pixelpower;
-
 	    bounds = CGRectMake(0, 0, image->width, image->height);
-	    srcRect = CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp);
+	    srcRect = CGRectMake(src_x, src_y, width, height);
 	    dstRect = CGRectMake(dest_x, dest_y, width, height);
 	    TkMacOSXDrawCGImage(drawable, gc, dc.context,
 				img, gc->foreground, gc->background,
diff --git macosx/tkMacOSXPrivate.h macosx/tkMacOSXPrivate.h
index a6b988eaf..d8372c1e4 100644
--- macosx/tkMacOSXPrivate.h
+++ macosx/tkMacOSXPrivate.h
@@ -205,11 +205,24 @@ typedef struct TkMacOSXDrawingContext {
     CGRect portBounds;
 } TkMacOSXDrawingContext;
 
+
+/*
+ * Enum for determining whether NSWindow has the backingScaleFactor
+ * property at runtime.
+ */
+
+typedef enum {
+    NSWINDOW_HAS_RETINA_UNKNOWN,
+    NSWINDOW_HAS_RETINA_NO,
+    NSWINDOW_HAS_RETINA_YES
+} TkMacOSXNSWindowHasRetinaEnum;
+
 /*
  * Variables internal to TkAqua.
  */
 
 MODULE_SCOPE long tkMacOSXMacOSXVersion;
+MODULE_SCOPE TkMacOSXNSWindowHasRetinaEnum tkMacOSXNSWindowHasRetina;
 
 /*
  * Prototypes for TkMacOSXRegion.c.
@@ -309,6 +322,7 @@ MODULE_SCOPE void       TkMacOSXWinNSBounds(TkWindow *winPtr, NSView *view,
 					    NSRect *bounds);
 MODULE_SCOPE void	TkMacOSXDrawAllViews(ClientData clientData);
 MODULE_SCOPE unsigned long TkMacOSXClearPixel(void);
+MODULE_SCOPE int	TkMacOSXNSWindowBackingScaleFactor(NSWindow *win);
 
 #pragma mark Private Objective-C Classes
 
diff --git xlib/X11/Xlib.h xlib/X11/Xlib.h
index 91aab571e..56d049c7a 100644
--- xlib/X11/Xlib.h
+++ xlib/X11/Xlib.h
@@ -330,9 +330,6 @@ typedef struct _XImage {
     unsigned long green_mask;
     unsigned long blue_mask;
     XPointer obdata;		/* hook for the object routines to hang on */
-#if defined(MAC_OSX_TK)
-    int pixelpower;		/* n such that pixels are 2^n x 2^n blocks*/
-#endif
     struct funcs {		/* image manipulation routines */
 	struct _XImage *(*create_image)();
 #if NeedFunctionPrototypes
-- 
2.28.0

