diff options
author | culler <culler> | 2017-11-15 02:42:00 (GMT) |
---|---|---|
committer | culler <culler> | 2017-11-15 02:42:00 (GMT) |
commit | f8dee9a0228dd40bdbf2c5494772f4d49c1b3659 (patch) | |
tree | 6b0c6f68da08737c0c64c7c0e347f9149f0661e4 /macosx | |
parent | bc151889837903b15310b5b9fb9ad5837b4a8b89 (diff) | |
download | tk-f8dee9a0228dd40bdbf2c5494772f4d49c1b3659.zip tk-f8dee9a0228dd40bdbf2c5494772f4d49c1b3659.tar.gz tk-f8dee9a0228dd40bdbf2c5494772f4d49c1b3659.tar.bz2 |
Make it possible to generate an NSImage with correct transparency from a
photoimage. Fixes transparency issues with iconphotos and images in menus.
Diffstat (limited to 'macosx')
-rw-r--r-- | macosx/tkMacOSXDraw.c | 2 | ||||
-rw-r--r-- | macosx/tkMacOSXImage.c | 84 | ||||
-rw-r--r-- | macosx/tkMacOSXInt.h | 2 | ||||
-rw-r--r-- | macosx/tkMacOSXPrivate.h | 3 | ||||
-rw-r--r-- | macosx/tkMacOSXXStubs.c | 1 |
5 files changed, 48 insertions, 44 deletions
diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 90ebd54..f40e5e6 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -443,7 +443,7 @@ TkMacOSXGetNSImageWithTkImage( MacDrawable *macDraw = (MacDrawable *) pixmap; NSImage *nsImage; - macDraw->flags |= TK_DO_NOT_BLEND; + macDraw->flags |= TK_USE_XIMAGE_ALPHA; Tk_RedrawImage(image, 0, 0, width, height, pixmap, 0, 0); nsImage = CreateNSImageWithPixmap(pixmap, width, height); Tk_FreePixmap(display, pixmap); diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c index adcb0f5..2436e60 100644 --- a/macosx/tkMacOSXImage.c +++ b/macosx/tkMacOSXImage.c @@ -46,7 +46,8 @@ static void ReleaseData(void *info, const void *data, size_t size) { CGImageRef TkMacOSXCreateCGImageWithXImage( - XImage *image) + XImage *image, + int use_ximage_alpha) { CGImageRef img = NULL; size_t bitsPerComponent, bitsPerPixel; @@ -96,8 +97,12 @@ TkMacOSXCreateCGImageWithXImage( bitsPerComponent = 8; bitsPerPixel = 32; bitmapInfo = (image->byte_order == MSBFirst ? - kCGBitmapByteOrder32Big : kCGBitmapByteOrder32Little) | - kCGImageAlphaNoneSkipFirst; + kCGBitmapByteOrder32Big : kCGBitmapByteOrder32Little); + if (use_ximage_alpha) { + bitmapInfo |= kCGImageAlphaPremultipliedFirst; + } else { + bitmapInfo |= kCGImageAlphaNoneSkipFirst; + } data = memcpy(ckalloc(len), image->data + image->xoffset, len); if (data) { provider = CGDataProviderCreateWithData(data, data, len, releaseData); @@ -163,20 +168,6 @@ XGetImage( MacDrawable *macDraw = ((MacDrawable*)drawable); static enum {unknown, no, yes} has_retina = unknown; - if (macDraw->flags & TK_DO_NOT_BLEND) { - /* - * When called by TkImgPhotoDisplay we are being asked to return a - * background image to be blended with the photoimage using its alpha - * channel, if it has one. Returning NULL here makes TkImgPhotoDisplay - * simply copy the image data, including the alpha channel, rather than - * do any blending. For example, when creating an iconphoto from a - * photoimage with transparency we will be passed a newly created - * pixmap filled with black pixels. These should not be blended with - * the pixels in the photoimage. - */ - return NULL; - } - if (win && has_retina == unknown) { #ifdef __clang__ has_retina = [win respondsToSelector:@selector(backingScaleFactor)]? @@ -221,7 +212,23 @@ XGetImage( CFRelease(bitmap_rep); return NULL; } - memcpy(bitmap, (char *)[bitmap_rep bitmapData], size); + + if (macDraw->flags & TK_USE_XIMAGE_ALPHA) { + /* + * When called by TkImgPhotoDisplay we are being asked to return a + * background image to be blended with the photoimage using its + * alpha channel, if it has one. Returning a black pixmap here + * makes TkImgPhotoDisplay create an XImage with a premultiplied + * alpha channel, as favored by Apple. When TkImgPhotoDisplay + * passes this XImage to TkPutImage, targeting a pixmap, it creates + * an image with correct transparency. This is used, for example, + * when creating an iconphoto or a menu image from a PNG + * photoimage. + */ + bzero(bitmap, size); + } else { + memcpy(bitmap, (char *)[bitmap_rep bitmapData], size); + } CFRelease(bitmap_rep); /* @@ -382,23 +389,16 @@ ImagePutPixel( unsigned long pixel) { if (image && image->data) { - unsigned char r = ((pixel & image->red_mask) >> 16) & 0xff; - unsigned char g = ((pixel & image->green_mask) >> 8) & 0xff; - unsigned char b = ((pixel & image->blue_mask) ) & 0xff; unsigned char *dstPtr = ((unsigned char*) image->data) + (y * image->bytes_per_line) + (((image->xoffset + x) * image->bits_per_pixel) / NBBY); - - switch (image->bits_per_pixel) { - case 32: - *((unsigned int*) dstPtr) = (0xff << 24) | (r << 16) | - (g << 8) | b; - /*if (image->byte_order == LSBFirst) { - dstPtr[3] = 0xff; dstPtr[2] = r; dstPtr[1] = g; dstPtr[0] = b; - } else { - dstPtr[0] = 0xff; dstPtr[1] = r; dstPtr[2] = g; dstPtr[3] = b; - }*/ - break; + if (image->bits_per_pixel == 32) { + *((unsigned int*) dstPtr) = pixel; + } else { + unsigned char r = ((pixel & image->red_mask) >> 16) & 0xff; + unsigned char g = ((pixel & image->green_mask) >> 8) & 0xff; + unsigned char b = ((pixel & image->blue_mask) ) & 0xff; + switch (image->bits_per_pixel) { case 16: *((unsigned short*) dstPtr) = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); @@ -418,6 +418,7 @@ ImagePutPixel( *dstPtr = ((r|g|b) & 0x80) ? (*dstPtr | (0x80 >> (x % 8))) : (*dstPtr & ~(0x80 >> (x % 8))); break; + } } } return 0; @@ -528,31 +529,32 @@ XCreateImage( int TkPutImage( unsigned long *colors, /* Unused on Macintosh. */ - int ncolors, /* Unused on Macintosh. */ + int ncolors, /* Unused on Macintosh. */ Display* display, /* Display. */ - Drawable d, /* Drawable to place image on. */ - GC gc, /* GC to use. */ + Drawable drawable, /* Drawable to place image on. */ + GC gc, /* GC to use. */ XImage* image, /* Image to place. */ int src_x, /* Source X & Y. */ int src_y, int dest_x, /* Destination X & Y. */ int dest_y, - unsigned int width, /* Same width & height for both */ + unsigned int width, /* Same width & height for both */ unsigned int height) /* distination and source. */ { TkMacOSXDrawingContext dc; - + MacDrawable *macDraw = ((MacDrawable*)drawable); + display->request++; - if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) { + if (!TkMacOSXSetupDrawingContext(drawable, gc, 1, &dc)) { return BadDrawable; } if (dc.context) { - CGImageRef img = TkMacOSXCreateCGImageWithXImage(image); - + CGImageRef img = TkMacOSXCreateCGImageWithXImage(image, + macDraw->flags & TK_USE_XIMAGE_ALPHA); if (img) { /* If the XImage has big pixels, rescale the source dimensions.*/ int pp = image->pixelpower; - TkMacOSXDrawCGImage(d, gc, dc.context, + TkMacOSXDrawCGImage(drawable, gc, dc.context, img, gc->foreground, gc->background, CGRectMake(0, 0, image->width<<pp, image->height<<pp), CGRectMake(src_x<<pp, src_y<<pp, width<<pp, height<<pp), diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index eb280a6..52be0e1 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -87,7 +87,7 @@ typedef struct TkWindowPrivate MacDrawable; #define TK_IS_PIXMAP 0x20 #define TK_IS_BW_PIXMAP 0x40 #define TK_DO_NOT_DRAW 0x80 -#define TK_DO_NOT_BLEND 0x100 +#define TK_USE_XIMAGE_ALPHA 0x100 /* * I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags * This is defined in tk.h. We need to duplicate the TK_EMBEDDED flag in the diff --git a/macosx/tkMacOSXPrivate.h b/macosx/tkMacOSXPrivate.h index 972b74c..ee7d5b3 100644 --- a/macosx/tkMacOSXPrivate.h +++ b/macosx/tkMacOSXPrivate.h @@ -211,7 +211,8 @@ MODULE_SCOPE int TkGenerateButtonEventForXPointer(Window window); MODULE_SCOPE EventModifiers TkMacOSXModifierState(void); MODULE_SCOPE NSBitmapImageRep* TkMacOSXBitmapRepFromDrawableRect(Drawable drawable, int x, int y, unsigned int width, unsigned int height); -MODULE_SCOPE CGImageRef TkMacOSXCreateCGImageWithXImage(XImage *image); +MODULE_SCOPE CGImageRef TkMacOSXCreateCGImageWithXImage(XImage *image, + int use_ximage_alpha); MODULE_SCOPE void TkMacOSXDrawCGImage(Drawable d, GC gc, CGContextRef context, CGImageRef image, unsigned long imageForeground, unsigned long imageBackground, CGRect imageBounds, diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index c7ff58d..1b0a246 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -200,6 +200,7 @@ TkpOpenDisplay( screen->root_visual = ckalloc(sizeof(Visual)); screen->root_visual->visualid = 0; screen->root_visual->class = TrueColor; + screen->root_visual->alpha_mask = 0xFF000000; screen->root_visual->red_mask = 0x00FF0000; screen->root_visual->green_mask = 0x0000FF00; screen->root_visual->blue_mask = 0x000000FF; |