From ad660115aaeb3951cc4a1db16d6c6edcb5efa132 Mon Sep 17 00:00:00 2001 From: culler Date: Wed, 8 Nov 2017 17:43:14 +0000 Subject: Reorganization to put all code related to Ximages in the new file tkMacOSXImage.c --- macosx/tkMacOSXDraw.c | 187 ++-------------- macosx/tkMacOSXImage.c | 559 +++++++++++++++++++++++++++++++++++++++++++++++ macosx/tkMacOSXPrivate.h | 8 +- macosx/tkMacOSXWm.c | 2 - macosx/tkMacOSXXStubs.c | 396 --------------------------------- unix/Makefile.in | 8 +- 6 files changed, 586 insertions(+), 574 deletions(-) create mode 100644 macosx/tkMacOSXImage.c diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 02ea812..274a2cd 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -16,7 +16,6 @@ #include "tkMacOSXPrivate.h" #include "tkMacOSXDebug.h" -#include "xbytes.h" #include "tkButton.h" /* @@ -45,12 +44,6 @@ static int useThemedFrame = 0; */ static void ClipToGC(Drawable d, GC gc, HIShapeRef *clipRgnPtr); -static CGImageRef CreateCGImageWithXImage(XImage *ximage); -static CGContextRef GetCGContextForDrawable(Drawable d); -static void DrawCGImage(Drawable d, GC gc, CGContextRef context, CGImageRef image, - unsigned long imageForeground, unsigned long imageBackground, - CGRect imageBounds, CGRect srcBounds, CGRect dstBounds); - /* *---------------------------------------------------------------------- @@ -108,7 +101,7 @@ TkMacOSXInitCGDrawing( /* *---------------------------------------------------------------------- * - * BitmapRepFromDrawableRect + * TkMacOSXBitmapRepFromDrawableRect * * Extract bitmap data from a MacOSX drawable as an NSBitmapImageRep. * @@ -126,7 +119,7 @@ TkMacOSXInitCGDrawing( *---------------------------------------------------------------------- */ NSBitmapImageRep* -BitmapRepFromDrawableRect( +TkMacOSXBitmapRepFromDrawableRect( Drawable drawable, int x, int y, @@ -143,7 +136,7 @@ BitmapRepFromDrawableRect( This means that the MacDrawable is functioning as a Tk Pixmap, so its view field is NULL. */ - cg_context = GetCGContextForDrawable(drawable); + cg_context = TkMacOSXGetCGContextForDrawable(drawable); CGRect image_rect = CGRectMake(x, y, width, height); cg_image = CGBitmapContextCreateImage( (CGContextRef) cg_context); sub_cg_image = CGImageCreateWithImageInRect(cg_image, image_rect); @@ -230,7 +223,7 @@ XCopyArea( if (srcDraw->flags & TK_IS_PIXMAP) { img = TkMacOSXCreateCGImageWithDrawable(src); }else if (TkMacOSXDrawableWindow(src)) { - bitmap_rep = BitmapRepFromDrawableRect(src, src_x, src_y, width, height); + bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(src, src_x, src_y, width, height); if ( bitmap_rep ) { img = [bitmap_rep CGImage]; } @@ -239,7 +232,7 @@ XCopyArea( } if (img) { - DrawCGImage(dst, gc, dc.context, img, gc->foreground, gc->background, + TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, gc->background, CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height), CGRectMake(src_x, src_y, width, height), CGRectMake(dest_x, dest_y, width, height)); @@ -339,7 +332,7 @@ XCopyPlane( CGImageRelease(submask); CGImageRelease(subimage); } else { - DrawCGImage(dst, gc, dc.context, img, gc->foreground, imageBackground, + TkMacOSXDrawCGImage(dst, gc, dc.context, img, gc->foreground, imageBackground, CGRectMake(0, 0, srcDraw->size.width, srcDraw->size.height), CGRectMake(src_x, src_y, width, height), CGRectMake(dest_x, dest_y, width, height)); @@ -360,158 +353,6 @@ XCopyPlane( /* *---------------------------------------------------------------------- * - * TkPutImage -- - * - * Copies a subimage from an in-memory image to a rectangle of - * of the specified drawable. - * - * Results: - * None. - * - * Side effects: - * Draws the image on the specified drawable. - * - *---------------------------------------------------------------------- - */ - -int -TkPutImage( - unsigned long *colors, /* Unused on Macintosh. */ - int ncolors, /* Unused on Macintosh. */ - Display* display, /* Display. */ - Drawable d, /* 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 height) /* distination and source. */ -{ - TkMacOSXDrawingContext dc; - - display->request++; - if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) { - return BadDrawable; - } - if (dc.context) { - 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<height<bytes_per_line * image->height; - const CGFloat *decode = NULL; - CGBitmapInfo bitmapInfo; - CGDataProviderRef provider = NULL; - char *data = NULL; - CGDataProviderReleaseDataCallback releaseData = ReleaseData; - - if (image->bits_per_pixel == 1) { - /* - * BW image - */ - - /* Reverses the sense of the bits */ - static const CGFloat decodeWB[2] = {1, 0}; - decode = decodeWB; - - bitsPerComponent = 1; - bitsPerPixel = 1; - if (image->bitmap_bit_order != MSBFirst) { - char *srcPtr = image->data + image->xoffset; - char *endPtr = srcPtr + len; - char *destPtr = (data = ckalloc(len)); - - while (srcPtr < endPtr) { - *destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))]; - } - } else { - data = memcpy(ckalloc(len), image->data + image->xoffset, len); - } - if (data) { - provider = CGDataProviderCreateWithData(data, data, len, releaseData); - } - if (provider) { - img = CGImageMaskCreate(image->width, image->height, bitsPerComponent, - bitsPerPixel, image->bytes_per_line, provider, decode, 0); - } - } else if (image->format == ZPixmap && image->bits_per_pixel == 32) { - /* - * Color image - */ - - CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); - - bitsPerComponent = 8; - bitsPerPixel = 32; - bitmapInfo = (image->byte_order == MSBFirst ? - kCGBitmapByteOrder32Big : kCGBitmapByteOrder32Little) | - kCGImageAlphaNoneSkipFirst; - data = memcpy(ckalloc(len), image->data + image->xoffset, len); - if (data) { - provider = CGDataProviderCreateWithData(data, data, len, releaseData); - } - if (provider) { - img = CGImageCreate(image->width, image->height, bitsPerComponent, - bitsPerPixel, image->bytes_per_line, colorspace, bitmapInfo, - provider, decode, 0, kCGRenderingIntentDefault); - CFRelease(provider); - } - if (colorspace) { - CFRelease(colorspace); - } - } else { - TkMacOSXDbgMsg("Unsupported image type"); - } - return img; -} - -/* - *---------------------------------------------------------------------- - * * TkMacOSXCreateCGImageWithDrawable -- * * Create a CGImage from the given Drawable. @@ -530,7 +371,7 @@ TkMacOSXCreateCGImageWithDrawable( Drawable drawable) { CGImageRef img = NULL; - CGContextRef context = GetCGContextForDrawable(drawable); + CGContextRef context = TkMacOSXGetCGContextForDrawable(drawable); if (context) { img = CGBitmapContextCreateImage(context); @@ -649,7 +490,7 @@ TkMacOSXGetNSImageWithBitmap( /* *---------------------------------------------------------------------- * - * GetCGContextForDrawable -- + * TkMacOSXGetCGContextForDrawable -- * * Get CGContext for given Drawable, creating one if necessary. * @@ -663,10 +504,10 @@ TkMacOSXGetNSImageWithBitmap( */ CGContextRef -GetCGContextForDrawable( - Drawable d) +TkMacOSXGetCGContextForDrawable( + Drawable drawable) { - MacDrawable *macDraw = (MacDrawable *) d; + MacDrawable *macDraw = (MacDrawable *) drawable; if (macDraw && (macDraw->flags & TK_IS_PIXMAP) && !macDraw->context) { const size_t bitsPerComponent = 8; @@ -711,7 +552,7 @@ GetCGContextForDrawable( /* *---------------------------------------------------------------------- * - * DrawCGImage -- + * TkMacOSXDrawCGImage -- * * Draw CG image into drawable. * @@ -725,7 +566,7 @@ GetCGContextForDrawable( */ void -DrawCGImage( +TkMacOSXDrawCGImage( Drawable d, GC gc, CGContextRef context, @@ -1625,7 +1466,7 @@ TkMacOSXSetupDrawingContext( goto end; } if (useCG) { - dc.context = GetCGContextForDrawable(d); + dc.context = TkMacOSXGetCGContextForDrawable(d); } if (!dc.context || !(macDraw->flags & TK_IS_PIXMAP)) { isWin = (TkMacOSXDrawableWindow(d) != nil); diff --git a/macosx/tkMacOSXImage.c b/macosx/tkMacOSXImage.c new file mode 100644 index 0000000..ac842f9 --- /dev/null +++ b/macosx/tkMacOSXImage.c @@ -0,0 +1,559 @@ +/* + * tkMacOSXImage.c -- + * + * The code in this file provides an interface for XImages, + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001-2009, Apple Inc. + * Copyright (c) 2005-2009 Daniel A. Steffen + * Copyright 2017 Marc Culler. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tkMacOSXPrivate.h" +#include "xbytes.h" + +#pragma mark XImage handling + +int +_XInitImageFuncPtrs( + XImage *image) +{ + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXCreateCGImageWithXImage -- + * + * Create CGImage from XImage, copying the image data. + * + * Results: + * CGImage, release after use. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void ReleaseData(void *info, const void *data, size_t size) { + ckfree(info); +} + +CGImageRef +TkMacOSXCreateCGImageWithXImage( + XImage *image) +{ + CGImageRef img = NULL; + size_t bitsPerComponent, bitsPerPixel; + size_t len = image->bytes_per_line * image->height; + const CGFloat *decode = NULL; + CGBitmapInfo bitmapInfo; + CGDataProviderRef provider = NULL; + char *data = NULL; + CGDataProviderReleaseDataCallback releaseData = ReleaseData; + + if (image->bits_per_pixel == 1) { + /* + * BW image + */ + + /* Reverses the sense of the bits */ + static const CGFloat decodeWB[2] = {1, 0}; + decode = decodeWB; + + bitsPerComponent = 1; + bitsPerPixel = 1; + if (image->bitmap_bit_order != MSBFirst) { + char *srcPtr = image->data + image->xoffset; + char *endPtr = srcPtr + len; + char *destPtr = (data = ckalloc(len)); + + while (srcPtr < endPtr) { + *destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))]; + } + } else { + data = memcpy(ckalloc(len), image->data + image->xoffset, len); + } + if (data) { + provider = CGDataProviderCreateWithData(data, data, len, releaseData); + } + if (provider) { + img = CGImageMaskCreate(image->width, image->height, bitsPerComponent, + bitsPerPixel, image->bytes_per_line, provider, decode, 0); + } + } else if (image->format == ZPixmap && image->bits_per_pixel == 32) { + /* + * Color image + */ + + CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); + + bitsPerComponent = 8; + bitsPerPixel = 32; + bitmapInfo = (image->byte_order == MSBFirst ? + kCGBitmapByteOrder32Big : kCGBitmapByteOrder32Little) | + kCGImageAlphaNoneSkipFirst; + data = memcpy(ckalloc(len), image->data + image->xoffset, len); + if (data) { + provider = CGDataProviderCreateWithData(data, data, len, releaseData); + } + if (provider) { + img = CGImageCreate(image->width, image->height, bitsPerComponent, + bitsPerPixel, image->bytes_per_line, colorspace, bitmapInfo, + provider, decode, 0, kCGRenderingIntentDefault); + CFRelease(provider); + } + if (colorspace) { + CFRelease(colorspace); + } + } else { + TkMacOSXDbgMsg("Unsupported image type"); + } + return img; +} + + +/* + *---------------------------------------------------------------------- + * + * XGetImage -- + * + * This function copies data from a pixmap or window into an XImage. + * + * 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. 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. + * + *---------------------------------------------------------------------- + */ + +XImage * +XGetImage( + Display *display, + Drawable d, + int x, + int y, + unsigned int width, + unsigned int height, + unsigned long plane_mask, + int format) +{ + NSBitmapImageRep *bitmap_rep; + NSUInteger bitmap_fmt; + XImage * imagePtr = NULL; + char * bitmap = NULL; + char * image_data=NULL; + int depth = 32; + int offset = 0; + int bitmap_pad = 0; + int bytes_per_row = 4*width; + int size; + int scalefactor = 1; +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + 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. + */ + if (win && [win respondsToSelector:@selector(backingScaleFactor)]) { + scalefactor = ([win backingScaleFactor] == 2.0) ? 2 : 1; + } +#endif + int scaled_height = height * scalefactor; + int scaled_width = width * scalefactor; + + if (format == ZPixmap) { + if (width == 0 || height == 0) { + /* This happens all the time. + TkMacOSXDbgMsg("XGetImage: empty image requested"); + */ + return NULL; + } + + bitmap_rep = TkMacOSXBitmapRepFromDrawableRect(d, x, y, width, height); + bitmap_fmt = [bitmap_rep bitmapFormat]; + + if ( bitmap_rep == Nil || + (bitmap_fmt != 0 && bitmap_fmt != 1) || + [bitmap_rep samplesPerPixel] != 4 || + [bitmap_rep isPlanar] != 0 ) { + TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep"); + return NULL; + } + + NSSize image_size = NSMakeSize(width, height); + NSImage* ns_image = [[NSImage alloc]initWithSize:image_size]; + [ns_image addRepresentation:bitmap_rep]; + + /* Assume premultiplied nonplanar data with 4 bytes per pixel.*/ + if ( [bitmap_rep isPlanar ] == 0 && + [bitmap_rep samplesPerPixel] == 4 ) { + bytes_per_row = [bitmap_rep bytesPerRow]; + 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; + bitmap = ckalloc(size); + /* + Oddly enough, the bitmap has the top row at the beginning, + and the pixels are in BGRA or ABGR format. + */ + if (bitmap_fmt == 0) { + /* BGRA */ + for (row=0, n=0; rowpixelpower = 1; + } + [ns_image removeRepresentation:bitmap_rep]; /*releases the rep*/ + [ns_image release]; + } + } else { + TkMacOSXDbgMsg("Could not extract image from drawable."); + } + return imagePtr; +} + +/* + *---------------------------------------------------------------------- + * + * DestroyImage -- + * + * Destroys storage associated with an image. + * + * Results: + * None. + * + * Side effects: + * Deallocates the image. + * + *---------------------------------------------------------------------- + */ + +static int +DestroyImage( + XImage *image) +{ + if (image) { + if (image->data) { + ckfree(image->data); + } + ckfree(image); + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * ImageGetPixel -- + * + * Get a single pixel from an image. + * + * Results: + * Returns the 32 bit pixel value. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static unsigned long +ImageGetPixel( + XImage *image, + int x, + int y) +{ + unsigned char r = 0, g = 0, b = 0; + + if (image && image->data) { + unsigned char *srcPtr = ((unsigned char*) image->data) + + (y * image->bytes_per_line) + + (((image->xoffset + x) * image->bits_per_pixel) / NBBY); + + switch (image->bits_per_pixel) { + case 32: { + r = (*((unsigned int*) srcPtr) >> 16) & 0xff; + g = (*((unsigned int*) srcPtr) >> 8) & 0xff; + b = (*((unsigned int*) srcPtr) ) & 0xff; + /*if (image->byte_order == LSBFirst) { + r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0]; + } else { + r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3]; + }*/ + break; + } + case 16: + r = (*((unsigned short*) srcPtr) >> 7) & 0xf8; + g = (*((unsigned short*) srcPtr) >> 2) & 0xf8; + b = (*((unsigned short*) srcPtr) << 3) & 0xf8; + break; + case 8: + r = (*srcPtr << 2) & 0xc0; + g = (*srcPtr << 4) & 0xc0; + b = (*srcPtr << 6) & 0xc0; + r |= r >> 2 | r >> 4 | r >> 6; + g |= g >> 2 | g >> 4 | g >> 6; + b |= b >> 2 | b >> 4 | b >> 6; + break; + case 4: { + unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4); + r = (c & 0x04) ? 0xff : 0; + g = (c & 0x02) ? 0xff : 0; + b = (c & 0x01) ? 0xff : 0; + break; + } + case 1: + r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0; + break; + } + } + return (PIXEL_MAGIC << 24) | (r << 16) | (g << 8) | b; +} + +/* + *---------------------------------------------------------------------- + * + * ImagePutPixel -- + * + * Set a single pixel in an image. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +ImagePutPixel( + XImage *image, + int x, + int y, + 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; + case 16: + *((unsigned short*) dstPtr) = ((r & 0xf8) << 7) | + ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); + break; + case 8: + *dstPtr = ((r & 0xc0) >> 2) | ((g & 0xc0) >> 4) | + ((b & 0xc0) >> 6); + break; + case 4: { + unsigned char c = ((r & 0x80) >> 5) | ((g & 0x80) >> 6) | + ((b & 0x80) >> 7); + *dstPtr = (x % 2) ? ((*dstPtr & 0xf0) | (c & 0x0f)) : + ((*dstPtr & 0x0f) | ((c << 4) & 0xf0)); + break; + } + case 1: + *dstPtr = ((r|g|b) & 0x80) ? (*dstPtr | (0x80 >> (x % 8))) : + (*dstPtr & ~(0x80 >> (x % 8))); + break; + } + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * XCreateImage -- + * + * Allocates storage for a new XImage. + * + * Results: + * Returns a newly allocated XImage. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +XImage * +XCreateImage( + Display* display, + Visual* visual, + unsigned int depth, + int format, + int offset, + char* data, + unsigned int width, + unsigned int height, + int bitmap_pad, + int bytes_per_line) +{ + XImage *ximage; + display->request++; + ximage = ckalloc(sizeof(XImage)); + + ximage->height = height; + ximage->width = width; + ximage->depth = depth; + ximage->xoffset = offset; + 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; + ximage->bitmap_unit = 32; + } else { + ximage->bits_per_pixel = 1; + ximage->bitmap_unit = 8; + } + if (bitmap_pad) { + ximage->bitmap_pad = bitmap_pad; + } else { + /* Use 16 byte alignment for best Quartz perfomance */ + ximage->bitmap_pad = 128; + } + if (bytes_per_line) { + ximage->bytes_per_line = bytes_per_line; + } else { + ximage->bytes_per_line = ((width * ximage->bits_per_pixel + + (ximage->bitmap_pad - 1)) >> 3) & + ~((ximage->bitmap_pad >> 3) - 1); + } +#ifdef WORDS_BIGENDIAN + ximage->byte_order = MSBFirst; + ximage->bitmap_bit_order = MSBFirst; +#else + ximage->byte_order = LSBFirst; + ximage->bitmap_bit_order = LSBFirst; +#endif + ximage->red_mask = 0x00FF0000; + ximage->green_mask = 0x0000FF00; + ximage->blue_mask = 0x000000FF; + ximage->f.create_image = NULL; + ximage->f.destroy_image = DestroyImage; + ximage->f.get_pixel = ImageGetPixel; + ximage->f.put_pixel = ImagePutPixel; + ximage->f.sub_image = NULL; + ximage->f.add_pixel = NULL; + + return ximage; +} + +/* + *---------------------------------------------------------------------- + * + * TkPutImage -- + * + * Copies a subimage from an in-memory image to a rectangle of + * of the specified drawable. + * + * Results: + * None. + * + * Side effects: + * Draws the image on the specified drawable. + * + *---------------------------------------------------------------------- + */ + +int +TkPutImage( + unsigned long *colors, /* Unused on Macintosh. */ + int ncolors, /* Unused on Macintosh. */ + Display* display, /* Display. */ + Drawable d, /* 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 height) /* distination and source. */ +{ + TkMacOSXDrawingContext dc; + + display->request++; + if (!TkMacOSXSetupDrawingContext(d, gc, 1, &dc)) { + return BadDrawable; + } + if (dc.context) { + CGImageRef img = TkMacOSXCreateCGImageWithXImage(image); + + if (img) { + /* If the XImage has big pixels, rescale the source dimensions.*/ + int pp = image->pixelpower; + TkMacOSXDrawCGImage(d, gc, dc.context, + img, gc->foreground, gc->background, + CGRectMake(0, 0, image->width<height<request++; - ximage = ckalloc(sizeof(XImage)); - - ximage->height = height; - ximage->width = width; - ximage->depth = depth; - ximage->xoffset = offset; - 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; - ximage->bitmap_unit = 32; - } else { - ximage->bits_per_pixel = 1; - ximage->bitmap_unit = 8; - } - if (bitmap_pad) { - ximage->bitmap_pad = bitmap_pad; - } else { - /* Use 16 byte alignment for best Quartz perfomance */ - ximage->bitmap_pad = 128; - } - if (bytes_per_line) { - ximage->bytes_per_line = bytes_per_line; - } else { - ximage->bytes_per_line = ((width * ximage->bits_per_pixel + - (ximage->bitmap_pad - 1)) >> 3) & - ~((ximage->bitmap_pad >> 3) - 1); - } -#ifdef WORDS_BIGENDIAN - ximage->byte_order = MSBFirst; - ximage->bitmap_bit_order = MSBFirst; -#else - ximage->byte_order = LSBFirst; - ximage->bitmap_bit_order = LSBFirst; -#endif - ximage->red_mask = 0x00FF0000; - ximage->green_mask = 0x0000FF00; - ximage->blue_mask = 0x000000FF; - ximage->f.create_image = NULL; - ximage->f.destroy_image = DestroyImage; - ximage->f.get_pixel = ImageGetPixel; - ximage->f.put_pixel = ImagePutPixel; - ximage->f.sub_image = NULL; - ximage->f.add_pixel = NULL; - - return ximage; -} - -/* - *---------------------------------------------------------------------- - * - * XGetImage -- - * - * This function copies data from a pixmap or window into an XImage. - * - * 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. 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. - * - *---------------------------------------------------------------------- - */ - -XImage * -XGetImage( - Display *display, - Drawable d, - int x, - int y, - unsigned int width, - unsigned int height, - unsigned long plane_mask, - int format) -{ - NSBitmapImageRep *bitmap_rep; - NSUInteger bitmap_fmt; - XImage * imagePtr = NULL; - char * bitmap = NULL; - char * image_data=NULL; - int depth = 32; - int offset = 0; - int bitmap_pad = 0; - int bytes_per_row = 4*width; - int size; - int scalefactor = 1; -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 - 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. - */ - if (win && [win respondsToSelector:@selector(backingScaleFactor)]) { - scalefactor = ([win backingScaleFactor] == 2.0) ? 2 : 1; - } -#endif - int scaled_height = height * scalefactor; - int scaled_width = width * scalefactor; - - if (format == ZPixmap) { - if (width == 0 || height == 0) { - /* This happens all the time. - TkMacOSXDbgMsg("XGetImage: empty image requested"); - */ - return NULL; - } - - bitmap_rep = BitmapRepFromDrawableRect(d, x, y, width, height); - bitmap_fmt = [bitmap_rep bitmapFormat]; - - if ( bitmap_rep == Nil || - (bitmap_fmt != 0 && bitmap_fmt != 1) || - [bitmap_rep samplesPerPixel] != 4 || - [bitmap_rep isPlanar] != 0 ) { - TkMacOSXDbgMsg("XGetImage: Failed to construct NSBitmapRep"); - return NULL; - } - - NSSize image_size = NSMakeSize(width, height); - NSImage* ns_image = [[NSImage alloc]initWithSize:image_size]; - [ns_image addRepresentation:bitmap_rep]; - - /* Assume premultiplied nonplanar data with 4 bytes per pixel.*/ - if ( [bitmap_rep isPlanar ] == 0 && - [bitmap_rep samplesPerPixel] == 4 ) { - bytes_per_row = [bitmap_rep bytesPerRow]; - 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; - bitmap = ckalloc(size); - /* - Oddly enough, the bitmap has the top row at the beginning, - and the pixels are in BGRA or ABGR format. - */ - if (bitmap_fmt == 0) { - /* BGRA */ - for (row=0, n=0; rowpixelpower = 1; - } - [ns_image removeRepresentation:bitmap_rep]; /*releases the rep*/ - [ns_image release]; - } - } else { - TkMacOSXDbgMsg("Could not extract image from drawable."); - } - return imagePtr; -} - -/* - *---------------------------------------------------------------------- - * - * DestroyImage -- - * - * Destroys storage associated with an image. - * - * Results: - * None. - * - * Side effects: - * Deallocates the image. - * - *---------------------------------------------------------------------- - */ - -static int -DestroyImage( - XImage *image) -{ - if (image) { - if (image->data) { - ckfree(image->data); - } - ckfree(image); - } - return 0; -} - -/* - *---------------------------------------------------------------------- - * - * ImageGetPixel -- - * - * Get a single pixel from an image. - * - * Results: - * Returns the 32 bit pixel value. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static unsigned long -ImageGetPixel( - XImage *image, - int x, - int y) -{ - unsigned char r = 0, g = 0, b = 0; - - if (image && image->data) { - unsigned char *srcPtr = ((unsigned char*) image->data) - + (y * image->bytes_per_line) - + (((image->xoffset + x) * image->bits_per_pixel) / NBBY); - - switch (image->bits_per_pixel) { - case 32: { - r = (*((unsigned int*) srcPtr) >> 16) & 0xff; - g = (*((unsigned int*) srcPtr) >> 8) & 0xff; - b = (*((unsigned int*) srcPtr) ) & 0xff; - /*if (image->byte_order == LSBFirst) { - r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0]; - } else { - r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3]; - }*/ - break; - } - case 16: - r = (*((unsigned short*) srcPtr) >> 7) & 0xf8; - g = (*((unsigned short*) srcPtr) >> 2) & 0xf8; - b = (*((unsigned short*) srcPtr) << 3) & 0xf8; - break; - case 8: - r = (*srcPtr << 2) & 0xc0; - g = (*srcPtr << 4) & 0xc0; - b = (*srcPtr << 6) & 0xc0; - r |= r >> 2 | r >> 4 | r >> 6; - g |= g >> 2 | g >> 4 | g >> 6; - b |= b >> 2 | b >> 4 | b >> 6; - break; - case 4: { - unsigned char c = (x % 2) ? *srcPtr : (*srcPtr >> 4); - r = (c & 0x04) ? 0xff : 0; - g = (c & 0x02) ? 0xff : 0; - b = (c & 0x01) ? 0xff : 0; - break; - } - case 1: - r = g = b = ((*srcPtr) & (0x80 >> (x % 8))) ? 0xff : 0; - break; - } - } - return (PIXEL_MAGIC << 24) | (r << 16) | (g << 8) | b; -} - -/* - *---------------------------------------------------------------------- - * - * ImagePutPixel -- - * - * Set a single pixel in an image. - * - * Results: - * None. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -ImagePutPixel( - XImage *image, - int x, - int y, - 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; - case 16: - *((unsigned short*) dstPtr) = ((r & 0xf8) << 7) | - ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); - break; - case 8: - *dstPtr = ((r & 0xc0) >> 2) | ((g & 0xc0) >> 4) | - ((b & 0xc0) >> 6); - break; - case 4: { - unsigned char c = ((r & 0x80) >> 5) | ((g & 0x80) >> 6) | - ((b & 0x80) >> 7); - *dstPtr = (x % 2) ? ((*dstPtr & 0xf0) | (c & 0x0f)) : - ((*dstPtr & 0x0f) | ((c << 4) & 0xf0)); - break; - } - case 1: - *dstPtr = ((r|g|b) & 0x80) ? (*dstPtr | (0x80 >> (x % 8))) : - (*dstPtr & ~(0x80 >> (x % 8))); - break; - } - } - return 0; -} - /* *---------------------------------------------------------------------- * diff --git a/unix/Makefile.in b/unix/Makefile.in index 96f1408..54f947e 100644 --- a/unix/Makefile.in +++ b/unix/Makefile.in @@ -394,8 +394,8 @@ X11_OBJS = tkUnix.o tkUnix3d.o tkUnixButton.o tkUnixColor.o tkUnixConfig.o \ AQUA_OBJS = tkMacOSXBitmap.o tkMacOSXButton.o tkMacOSXClipboard.o \ tkMacOSXColor.o tkMacOSXConfig.o tkMacOSXCursor.o tkMacOSXDebug.o \ tkMacOSXDialog.o tkMacOSXDraw.o tkMacOSXEmbed.o tkMacOSXEntry.o \ - tkMacOSXEvent.o tkMacOSXFont.o tkMacOSXHLEvents.o tkMacOSXInit.o \ - tkMacOSXKeyboard.o tkMacOSXKeyEvent.o tkMacOSXMenu.o \ + tkMacOSXEvent.o tkMacOSXFont.o tkMacOSXHLEvents.o tkMacOSXImage.o \ + tkMacOSXInit.o tkMacOSXKeyboard.o tkMacOSXKeyEvent.o tkMacOSXMenu.o \ tkMacOSXMenubutton.o tkMacOSXMenus.o tkMacOSXMouseEvent.o \ tkMacOSXNotify.o tkMacOSXRegion.o tkMacOSXScrlbr.o tkMacOSXSend.o \ tkMacOSXSubwindows.o tkMacOSXWindowEvent.o \ @@ -519,6 +519,7 @@ AQUA_SRCS = \ $(MAC_OSX_DIR)/tkMacOSXDraw.c $(MAC_OSX_DIR)/tkMacOSXEmbed.c \ $(MAC_OSX_DIR)/tkMacOSXEntry.c $(MAC_OSX_DIR)/tkMacOSXEvent.c \ $(MAC_OSX_DIR)/tkMacOSXFont.c $(MAC_OSX_DIR)/tkMacOSXHLEvents.c \ + $(MAC_OSX_DIR)/tkMacOSXImage.c \ $(MAC_OSX_DIR)/tkMacOSXInit.c $(MAC_OSX_DIR)/tkMacOSXKeyboard.c \ $(MAC_OSX_DIR)/tkMacOSXKeyEvent.c $(MAC_OSX_DIR)/tkMacOSXMenu.c \ $(MAC_OSX_DIR)/tkMacOSXMenubutton.c $(MAC_OSX_DIR)/tkMacOSXMenus.c \ @@ -1272,6 +1273,9 @@ tkMacOSXFont.o: $(MAC_OSX_DIR)/tkMacOSXFont.c tkMacOSXHLEvents.o: $(MAC_OSX_DIR)/tkMacOSXHLEvents.c $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXHLEvents.c +tkMacOSXImage.o: $(MAC_OSX_DIR)/tkMacOSXImage.c + $(CC) -c $(CC_SWITCHES) $(MAC_OSX_DIR)/tkMacOSXImage.c + tkMacOSXInit.o: $(MAC_OSX_DIR)/tkMacOSXInit.c tkConfig.sh $(CC) -c $(CC_SWITCHES) -DTK_LIBRARY=\"${TK_LIBRARY}\" \ $(MAC_OSX_DIR)/tkMacOSXInit.c -- cgit v0.12