diff options
author | Kevin Walzer <kw@codebykevin.com> | 2016-07-15 10:47:18 (GMT) |
---|---|---|
committer | Kevin Walzer <kw@codebykevin.com> | 2016-07-15 10:47:18 (GMT) |
commit | 2ae13e10ac2c3c86584cece38298da049533e803 (patch) | |
tree | 2709070b1ea361c2ed7993c57f868eadb0a34720 /macosx | |
parent | c32ea9203392ec7c24b873842e0d0d84b66830cc (diff) | |
download | tk-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')
-rw-r--r-- | macosx/tkMacOSXDraw.c | 6 | ||||
-rw-r--r-- | macosx/tkMacOSXXStubs.c | 37 |
2 files changed, 34 insertions, 9 deletions
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index d9b909b..f48538d 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -399,9 +399,11 @@ TkPutImage( CGImageRef img = CreateCGImageWithXImage(image); if (img) { + /* If the XImage has big pixels, rescale the source dimensions.*/ + int pp = image->pixelpower; DrawCGImage(d, gc, dc.context, img, gc->foreground, gc->background, - CGRectMake(0, 0, image->width, image->height), - CGRectMake(src_x, src_y, width, height), + CGRectMake(0, 0, image->width<<pp, image->height<<pp), + CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp), CGRectMake(dest_x, dest_y, width, height)); CFRelease(img); } else { 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]; } |