Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix for alpha channel rendering for images on OS X Mavericks; thanks to Marc Culler for the extensive patch. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
9ec3b3c8ce1a631a5e31b0d984525aab |
User & Date: | kevin_walzer 2014-07-07 01:09:27 |
Context
2014-07-08
| ||
14:14 | merge-mark check-in: 56637bf8 user: jan.nijtmans tags: trunk | |
2014-07-07
| ||
01:09 | Fix for alpha channel rendering for images on OS X Mavericks; thanks to Marc Culler for the extensive patch. check-in: 9ec3b3c8 user: kevin_walzer tags: trunk | |
2014-06-30
| ||
11:28 | Eliminate last two calls to Tcl_CreateCommand(). check-in: aab5111f user: jan.nijtmans tags: trunk | |
Changes
Changes to macosx/tkMacOSXDraw.c.
︙ | ︙ | |||
110 111 112 113 114 115 116 117 118 | } return TCL_OK; } /* *---------------------------------------------------------------------- * * XCopyArea -- * | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | } return TCL_OK; } /* *---------------------------------------------------------------------- * * BitmapRepFromDrawableRect * * Extract bitmap data from a MacOSX drawable as an NSBitmapImageRep. * * Results: * Returns an autoreleased NSBitmapRep representing the image of the given * rectangle of the given drawable. * * NOTE: The x,y coordinates should be relative to a coordinate system with * origin at the top left, as used by XImage and CGImage, not bottom * left as used by NSView. * * Side effects: * None * *---------------------------------------------------------------------- */ NSBitmapImageRep* BitmapRepFromDrawableRect( Drawable drawable, int x, int y, unsigned int width, unsigned int height) { MacDrawable *mac_drawable = (MacDrawable *) drawable; CGContextRef cg_context=NULL; CGImageRef cg_image=NULL, sub_cg_image=NULL; NSBitmapImageRep *bitmap_rep=NULL; NSView *view=NULL; if ( mac_drawable->flags & TK_IS_PIXMAP ) { /* This means that the MacDrawable is functioning as a Tk Pixmap, so its view field is NULL. It's context field should point to a CGImage. */ cg_context = GetCGContextForDrawable(drawable); CGRect image_rect = CGRectMake(x, y, width, height); cg_image = CGBitmapContextCreateImage( (CGContextRef) cg_context); sub_cg_image = CGImageCreateWithImageInRect(cg_image, image_rect); if ( sub_cg_image ) { bitmap_rep = [[NSBitmapImageRep alloc] autorelease]; [bitmap_rep initWithCGImage:sub_cg_image]; } if ( cg_image ) { CGImageRelease(cg_image); } } else if ( (view = TkMacOSXDrawableView(mac_drawable)) ) { /* convert top-left coordinates to NSView coordinates */ int view_height = [view bounds].size.height; NSRect view_rect = NSMakeRect(x + mac_drawable->xOff, view_height - height - y - mac_drawable->yOff, width,height); if ( [view lockFocusIfCanDraw] ) { bitmap_rep = [[NSBitmapImageRep alloc] autorelease]; bitmap_rep = [bitmap_rep initWithFocusedViewRect:view_rect]; [view unlockFocus]; } else { TkMacOSXDbgMsg("Could not lock focus on view."); } } else { TkMacOSXDbgMsg("Invalid source drawable"); } return bitmap_rep; } /* *---------------------------------------------------------------------- * * XCopyArea -- * * Copies data from one drawable to another. * * Results: * None. * * Side effects: * Data is moved from a window or bitmap to a second window or * bitmap. |
︙ | ︙ | |||
140 141 142 143 144 145 146 147 148 149 | unsigned int width, /* that will be copied. */ unsigned int height, int dest_x, /* Dest X & Y on dest rect. */ int dest_y) { TkMacOSXDrawingContext dc; MacDrawable *srcDraw = (MacDrawable *) src; display->request++; if (!width || !height) { | > > > > > > | > | | | | > | > | > > > > | > > > > | | < | | | | | > | | < < < < < < < < < < < < < < < < < | | < < < < < < < < < < < < < < < < < < < < < | < < < | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | unsigned int width, /* that will be copied. */ unsigned int height, int dest_x, /* Dest X & Y on dest rect. */ int dest_y) { TkMacOSXDrawingContext dc; MacDrawable *srcDraw = (MacDrawable *) src; NSBitmapImageRep *bitmap_rep = NULL; CGImageRef img = NULL; display->request++; TkMacOSXDbgMsg("XCopyArea"); if (!width || !height) { /* This happens all the time. TkMacOSXDbgMsg("Drawing of empty area requested"); */ return; } if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) { TkMacOSXDbgMsg("Failed to setup drawing context."); } if ( dc.context ) { if (srcDraw->flags & TK_IS_PIXMAP) { img = TkMacOSXCreateCGImageWithDrawable(src); }else if (TkMacOSXDrawableWindow(src)) { bitmap_rep = BitmapRepFromDrawableRect(src, src_x, src_y, width, height); if ( bitmap_rep ) { img = [bitmap_rep CGImage]; } } else { TkMacOSXDbgMsg("Invalid source drawable"); } if (img) { DrawCGImage(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)); CFRelease(img); } else { TkMacOSXDbgMsg("Invalid source drawable"); } } else { TkMacOSXDbgMsg("Invalid destination drawable"); return; } TkMacOSXRestoreDrawingContext(&dc); } /* *---------------------------------------------------------------------- * * XCopyPlane -- * |
︙ | ︙ | |||
250 251 252 253 254 255 256 | unsigned long plane) /* Which plane to copy. */ { TkMacOSXDrawingContext dc; MacDrawable *srcDraw = (MacDrawable *) src; display->request++; if (!width || !height) { | | | 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 | unsigned long plane) /* Which plane to copy. */ { TkMacOSXDrawingContext dc; MacDrawable *srcDraw = (MacDrawable *) src; display->request++; if (!width || !height) { /* TkMacOSXDbgMsg("Drawing of empty area requested"); */ return; } if (plane != 1) { Tcl_Panic("Unexpected plane specified for XCopyPlane"); } if (srcDraw->flags & TK_IS_PIXMAP) { if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) { |
︙ | ︙ | |||
380 381 382 383 384 385 386 | size_t len = image->bytes_per_line * image->height; const CGFloat *decode = NULL; CGBitmapInfo bitmapInfo; CGDataProviderRef provider = NULL; char *data = NULL; CGDataProviderReleaseDataCallback releaseData = ReleaseData; | < < < < < < | | 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | 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 */ static const CGFloat decodeWB[2] = {1, 0}; bitsPerComponent = 1; |
︙ | ︙ |
Changes to macosx/tkMacOSXPrivate.h.
︙ | ︙ | |||
226 227 228 229 230 231 232 233 234 235 236 237 238 239 | int antiAlias); MODULE_SCOPE int TkMacOSXGenerateFocusEvent(TkWindow *winPtr, int activeFlag); MODULE_SCOPE WindowClass TkMacOSXWindowClass(TkWindow *winPtr); MODULE_SCOPE int TkMacOSXIsWindowZoomed(TkWindow *winPtr); MODULE_SCOPE int TkGenerateButtonEventForXPointer(Window window); MODULE_SCOPE EventModifiers TkMacOSXModifierState(void); MODULE_SCOPE int TkMacOSXSetupDrawingContext(Drawable d, GC gc, int useCG, TkMacOSXDrawingContext *dcPtr); MODULE_SCOPE void TkMacOSXRestoreDrawingContext( TkMacOSXDrawingContext *dcPtr); MODULE_SCOPE void TkMacOSXSetColorInContext(GC gc, unsigned long pixel, CGContextRef context); MODULE_SCOPE int TkMacOSXMakeFullscreen(TkWindow *winPtr, | > > | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | int antiAlias); MODULE_SCOPE int TkMacOSXGenerateFocusEvent(TkWindow *winPtr, int activeFlag); MODULE_SCOPE WindowClass TkMacOSXWindowClass(TkWindow *winPtr); MODULE_SCOPE int TkMacOSXIsWindowZoomed(TkWindow *winPtr); MODULE_SCOPE int TkGenerateButtonEventForXPointer(Window window); MODULE_SCOPE EventModifiers TkMacOSXModifierState(void); MODULE_SCOPE NSBitmapImageRep* BitmapRepFromDrawableRect(Drawable drawable, int x, int y, unsigned int width, unsigned int height); MODULE_SCOPE int TkMacOSXSetupDrawingContext(Drawable d, GC gc, int useCG, TkMacOSXDrawingContext *dcPtr); MODULE_SCOPE void TkMacOSXRestoreDrawingContext( TkMacOSXDrawingContext *dcPtr); MODULE_SCOPE void TkMacOSXSetColorInContext(GC gc, unsigned long pixel, CGContextRef context); MODULE_SCOPE int TkMacOSXMakeFullscreen(TkWindow *winPtr, |
︙ | ︙ |
Changes to macosx/tkMacOSXSubwindows.c.
︙ | ︙ | |||
1273 1274 1275 1276 1277 1278 1279 | * * Creates an in memory drawing surface. * * Results: * Returns a handle to a new pixmap. * * Side effects: | | | 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 | * * Creates an in memory drawing surface. * * Results: * Returns a handle to a new pixmap. * * Side effects: * Allocates a new CGBitmapContext. * *---------------------------------------------------------------------- */ Pixmap Tk_GetPixmap( Display *display, /* Display for new pixmap (can be null). */ |
︙ | ︙ | |||
1319 1320 1321 1322 1323 1324 1325 | * * Release the resources associated with a pixmap. * * Results: * None. * * Side effects: | | | 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 | * * Release the resources associated with a pixmap. * * Results: * None. * * Side effects: * Deletes the CGBitmapContext created by Tk_GetPixmap. * *---------------------------------------------------------------------- */ void Tk_FreePixmap( Display *display, /* Display. */ |
︙ | ︙ |
Changes to macosx/tkMacOSXXStubs.c.
︙ | ︙ | |||
778 779 780 781 782 783 784 | char* data, unsigned int width, unsigned int height, int bitmap_pad, int bytes_per_line) { XImage *ximage; | < > | 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 | 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; if (format == ZPixmap) { ximage->bits_per_pixel = 32; ximage->bitmap_unit = 32; } else { ximage->bits_per_pixel = 1; ximage->bitmap_unit = 8; |
︙ | ︙ | |||
819 820 821 822 823 824 825 | #else ximage->byte_order = LSBFirst; ximage->bitmap_bit_order = LSBFirst; #endif ximage->red_mask = 0x00FF0000; ximage->green_mask = 0x0000FF00; ximage->blue_mask = 0x000000FF; | < | | > | | < < | | | | | | | > | | < > | > | < | < < > > > | | > | | > > > | | | | | | | < < | | < | > | > | < | > > > > > > | < < < | > > | | > > > | | 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 | #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. * * 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; 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; TkMacOSXDbgMsg("XGetImage"); 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); if ( bitmap_rep == Nil || [bitmap_rep bitmapFormat] != 0 || [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 and alpha last.*/ if ( [bitmap_rep bitmapFormat] == 0 && [bitmap_rep isPlanar ] == 0 && [bitmap_rep samplesPerPixel] == 4 ) { bytes_per_row = [bitmap_rep bytesPerRow]; size = bytes_per_row*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 format. */ for (row=0, n=0; row<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); *(bitmap+m+2) = *(image_data+m); *(bitmap+m+3) = *(image_data+m+3); } } } } if (bitmap) { imagePtr = XCreateImage(display, NULL, depth, format, offset, (char*)bitmap, width, height, bitmap_pad, bytes_per_row); [ns_image removeRepresentation:bitmap_rep]; /*releases the rep*/ [ns_image release]; } } else { TkMacOSXDbgMsg("Could not extract image from drawable."); } return imagePtr; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
937 938 939 940 941 942 943 | */ static int DestroyImage( XImage *image) { if (image) { | < < | | 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 | */ static int DestroyImage( XImage *image) { if (image) { if (image->data) { ckfree(image->data); } ckfree(image); } return 0; } |
︙ | ︙ |