summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tkImgPhInstance.c18
-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
-rw-r--r--xlib/X11/Xlib.h4
7 files changed, 70 insertions, 44 deletions
diff --git a/generic/tkImgPhInstance.c b/generic/tkImgPhInstance.c
index fd98c6e..75f11f0 100644
--- a/generic/tkImgPhInstance.c
+++ b/generic/tkImgPhInstance.c
@@ -418,6 +418,13 @@ TkImgPhotoGet(
(UCHAR(r) << red_shift) | \
(UCHAR(g) << green_shift) | \
(UCHAR(b) << blue_shift) ))
+#ifdef MAC_OSX_TK
+#define RGBA(r, g, b, a) ((unsigned)( \
+ (UCHAR(r) << red_shift) | \
+ (UCHAR(g) << green_shift) | \
+ (UCHAR(b) << blue_shift) | \
+ (UCHAR(a) << alpha_shift) ))
+#endif
#define RGB15(r, g, b) ((unsigned)( \
(((r) * red_mask / 255) & red_mask) | \
(((g) * green_mask / 255) & green_mask) | \
@@ -485,6 +492,13 @@ BlendComplexAlpha(
while ((0x0001 & (blue_mask >> blue_shift)) == 0) {
blue_shift++;
}
+#ifdef MAC_OSX_TK
+ unsigned long alpha_mask = visual->alpha_mask;
+ unsigned long alpha_shift = 0;
+ while ((0x0001 & (alpha_mask >> alpha_shift)) == 0) {
+ alpha_shift++;
+ }
+#endif
#endif /* !_WIN32 */
/*
@@ -585,7 +599,11 @@ BlendComplexAlpha(
g = ALPHA_BLEND(ga, g, alpha, unalpha);
b = ALPHA_BLEND(ba, b, alpha, unalpha);
}
+#ifndef MAC_OSX_TK
XPutPixel(bgImg, x, y, RGB(r, g, b));
+#else
+ XPutPixel(bgImg, x, y, RGBA(r, g, b, alpha));
+#endif
}
}
}
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;
diff --git a/xlib/X11/Xlib.h b/xlib/X11/Xlib.h
index 8d8ec68..b027e28 100644
--- a/xlib/X11/Xlib.h
+++ b/xlib/X11/Xlib.h
@@ -203,6 +203,9 @@ typedef struct {
int class; /* class of screen (monochrome, etc.) */
#endif
unsigned long red_mask, green_mask, blue_mask; /* mask values */
+#if defined(MAC_OSX_TK)
+ unsigned long alpha_mask;
+#endif
int bits_per_rgb; /* log base 2 of distinct color values */
int map_entries; /* color map entries */
} Visual;
@@ -332,6 +335,7 @@ typedef struct _XImage {
XPointer obdata; /* hook for the object routines to hang on */
#if defined(MAC_OSX_TK)
int pixelpower; /* n such that pixels are 2^n x 2^n blocks*/
+ unsigned long alpha_mask;
#endif
struct funcs { /* image manipulation routines */
struct _XImage *(*create_image)();