summaryrefslogtreecommitdiffstats
path: root/macosx
diff options
context:
space:
mode:
authorculler <culler>2017-11-15 02:42:00 (GMT)
committerculler <culler>2017-11-15 02:42:00 (GMT)
commitf8dee9a0228dd40bdbf2c5494772f4d49c1b3659 (patch)
tree6b0c6f68da08737c0c64c7c0e347f9149f0661e4 /macosx
parentbc151889837903b15310b5b9fb9ad5837b4a8b89 (diff)
downloadtk-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.c2
-rw-r--r--macosx/tkMacOSXImage.c84
-rw-r--r--macosx/tkMacOSXInt.h2
-rw-r--r--macosx/tkMacOSXPrivate.h3
-rw-r--r--macosx/tkMacOSXXStubs.c1
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;