summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXXStubs.c
diff options
context:
space:
mode:
authorKevin Walzer <kw@codebykevin.com>2016-07-15 10:47:18 (GMT)
committerKevin Walzer <kw@codebykevin.com>2016-07-15 10:47:18 (GMT)
commit2ae13e10ac2c3c86584cece38298da049533e803 (patch)
tree2709070b1ea361c2ed7993c57f868eadb0a34720 /macosx/tkMacOSXXStubs.c
parentc32ea9203392ec7c24b873842e0d0d84b66830cc (diff)
downloadtk-2ae13e10ac2c3c86584cece38298da049533e803.zip
tk-2ae13e10ac2c3c86584cece38298da049533e803.tar.gz
tk-2ae13e10ac2c3c86584cece38298da049533e803.tar.bz2
Fix for image/alpha rendering under hidpi/Retina displays on Mac OS; thanks to Marc Culler for assistance
Diffstat (limited to 'macosx/tkMacOSXXStubs.c')
-rw-r--r--macosx/tkMacOSXXStubs.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c
index 5d6ffb9..a2d175b 100644
--- a/macosx/tkMacOSXXStubs.c
+++ b/macosx/tkMacOSXXStubs.c
@@ -805,6 +805,10 @@ XCreateImage(
ximage->format = format;
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;
@@ -856,7 +860,8 @@ XCreateImage(
* 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.
+ * 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.
*
* Side effects:
* None.
@@ -885,7 +890,19 @@ XGetImage(
int bitmap_pad = 0;
int bytes_per_row = 4*width;
int size;
- TkMacOSXDbgMsg("XGetImage");
+ MacDrawable *macDraw = (MacDrawable *) d;
+ NSWindow *win = TkMacOSXDrawableWindow(d);
+ /* This code assumes that backing scale factors are integers. Currently
+ * Retina displays use a scale factor of 2.0 and normal displays use 1.0.
+ * We do not support any other values here.
+ */
+ int scalefactor = 1;
+ if (win && [win respondsToSelector:@selector(backingScaleFactor)]) {
+ scalefactor = ([win backingScaleFactor] == 2.0) ? 2 : 1;
+ }
+ int scaled_height = height * scalefactor;
+ int scaled_width = width * scalefactor;
+
if (format == ZPixmap) {
if (width == 0 || height == 0) {
/* This happens all the time.
@@ -894,7 +911,7 @@ XGetImage(
return NULL;
}
- bitmap_rep = BitmapRepFromDrawableRect(d, x, y,width, height);
+ bitmap_rep = BitmapRepFromDrawableRect(d, x, y, width, height);
bitmap_fmt = [bitmap_rep bitmapFormat];
if ( bitmap_rep == Nil ||
@@ -913,7 +930,9 @@ XGetImage(
if ( [bitmap_rep isPlanar ] == 0 &&
[bitmap_rep samplesPerPixel] == 4 ) {
bytes_per_row = [bitmap_rep bytesPerRow];
- size = bytes_per_row*height;
+ assert(bytes_per_row == 4 * scaled_width);
+ assert([bitmap_rep bytesPerPlane] == bytes_per_row * scaled_height);
+ size = bytes_per_row*scaled_height;
image_data = (char*)[bitmap_rep bitmapData];
if ( image_data ) {
int row, n, m;
@@ -924,7 +943,7 @@ XGetImage(
*/
if (bitmap_fmt == 0) {
/* BGRA */
- for (row=0, n=0; row<height; row++, n+=bytes_per_row) {
+ for (row=0, n=0; row<scaled_height; row++, n+=bytes_per_row) {
for (m=n; m<n+bytes_per_row; m+=4) {
*(bitmap+m) = *(image_data+m+2);
*(bitmap+m+1) = *(image_data+m+1);
@@ -934,7 +953,7 @@ XGetImage(
}
} else {
/* ABGR */
- for (row=0, n=0; row<height; row++, n+=bytes_per_row) {
+ for (row=0, n=0; row<scaled_height; row++, n+=bytes_per_row) {
for (m=n; m<n+bytes_per_row; m+=4) {
*(bitmap+m) = *(image_data+m+3);
*(bitmap+m+1) = *(image_data+m+2);
@@ -947,7 +966,11 @@ XGetImage(
}
if (bitmap) {
imagePtr = XCreateImage(display, NULL, depth, format, offset,
- (char*)bitmap, width, height, bitmap_pad, bytes_per_row);
+ (char*)bitmap, scaled_width, scaled_height,
+ bitmap_pad, bytes_per_row);
+ if (scalefactor == 2) {
+ imagePtr->pixelpower = 1;
+ }
[ns_image removeRepresentation:bitmap_rep]; /*releases the rep*/
[ns_image release];
}