Attachment "0005-Aqua-X11-emulation-support-Retina-window-source.patch" to
ticket [685ac307]
added by
chrstphrchvz
2020-11-15 10:47:41.
From c63cf60ce4983044a8996953ad080292c8799a59 Mon Sep 17 00:00:00 2001
From: Christopher Chavez <[email protected]>
Date: Fri, 14 Aug 2020 08:48:06 -0500
Subject: [PATCH 5/5] Aqua X11 emulation: support Retina window source
Existing programs/libraries expect XGetImage() to return either an
XImage with the requested width and height, or NULL. This means that
a capture of a real window on a Retina display must be downscaled
before being returned by XGetImage() for compatibility.
To support this, a parameter force_1x_scale is added to
CreateCGImageFromDrawableRect(), which if true will downscale the
returned CGImage to the requested width and height. Otherwise,
capturing a window on a Retina display will return a CGImage having
twice the requested width and height.
If programs should be able to retrieve unscaled captures of windows on
Retina displays, then a separate API is needed. See
https://core.tcl-lang.org/tk/info/fcd6717d8b
Not fully tested. Would be particularly interested in a way to test
XCopyArea() between non-pixmaps. XCopyPlane() might be unfinished.
---
macosx/tkMacOSXImage.c | 37 +++++++++++++++++++++++++++++++++++--
1 file changed, 35 insertions(+), 2 deletions(-)
diff --git macosx/tkMacOSXImage.c macosx/tkMacOSXImage.c
index 34177586e..47060e2d8 100644
--- macosx/tkMacOSXImage.c
+++ macosx/tkMacOSXImage.c
@@ -17,6 +17,7 @@
static CGImageRef CreateCGImageFromPixmap(Drawable pixmap);
static CGImageRef CreateCGImageFromDrawableRect( Drawable drawable,
+ int force_1x_scale,
int x, int y, unsigned int width, unsigned int height);
#pragma mark XImage handling
@@ -498,6 +499,11 @@ TkPutImage(
* with origin at the top left, as used by XImage and CGImage, not bottom
* left as used by NSView.
*
+ * If force_1x_scale is true, then the returned CGImage will be downscaled
+ * if necessary to have the requested width and height. Othewise, for
+ * windows on Retina displays, the width and height of the returned CGImage
+ * will be twice the requested width and height.
+ *
* Side effects:
* If successful, allocates a new CGImage.
*
@@ -507,6 +513,7 @@ TkPutImage(
static CGImageRef
CreateCGImageFromDrawableRect(
Drawable drawable,
+ int force_1x_scale,
int x,
int y,
unsigned int width,
@@ -531,6 +538,8 @@ CreateCGImageFromDrawableRect(
CGImageRelease(cg_image);
}
} else if ((view = TkMacOSXGetNSViewForDrawable(mac_drawable)) != nil) {
+ CGFloat scaleFactor = TkMacOSXNSWindowBackingScaleFactor(
+ [view window]);
/*
* Convert Tk top-left to NSView bottom-left coordinates.
@@ -571,6 +580,28 @@ CreateCGImageFromDrawableRect(
result = [bitmapRep CGImage];
CGImageRetain(result);
[bitmapRep release];
+ if (force_1x_scale && (scaleFactor != 1.0)) {
+ cg_image = result;
+ result = NULL;
+ // See http://blog.foundry376.com/2008/07/scaling-a-cgimage/#comment-200
+ // create context, keeping original image properties
+ CGColorSpaceRef colorspace = CGImageGetColorSpace(cg_image);
+ cg_context = CGBitmapContextCreate(NULL, width, height,
+ CGImageGetBitsPerComponent(cg_image),
+ CGImageGetBytesPerRow(cg_image),
+ colorspace,
+ CGImageGetAlphaInfo(cg_image));
+ CGColorSpaceRelease(colorspace);
+ if (cg_context) {
+ // draw image to context (resizing it)
+ CGContextDrawImage(cg_context, CGRectMake(0, 0, width, height),
+ cg_image);
+ // extract resulting image from context
+ result = CGBitmapContextCreateImage(cg_context);
+ CGContextRelease(cg_context);
+ }
+ CGImageRelease(cg_image);
+ }
} else {
TkMacOSXDbgMsg("Invalid source drawable");
}
@@ -697,7 +728,8 @@ XGetImage(
return NULL;
}
- cgImage = CreateCGImageFromDrawableRect(drawable, x, y, width, height);
+ // Request 1x-scale image for compatibility
+ cgImage = CreateCGImageFromDrawableRect(drawable, 1, x, y, width, height);
if (cgImage) {
bitmapRep = [NSBitmapImageRep alloc];
[bitmapRep initWithCGImage:cgImage];
@@ -805,7 +837,8 @@ XCopyArea(
return BadDrawable;
}
- img = CreateCGImageFromDrawableRect(src, src_x, src_y, width, height);
+ // Use unscaled source (TkMacOSXDrawCGImage() will implicitly downscale)
+ img = CreateCGImageFromDrawableRect(src, 0, src_x, src_y, width, height);
if (img) {
dstRect = CGRectMake(dest_x, dest_y, width, height);
--
2.24.3 (Apple Git-128)