Tk Source Code

Check-in [9ec3b3c8]
Login

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: 9ec3b3c8ce1a631a5e31b0d984525aab6e0396f8
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
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to macosx/tkMacOSXDraw.c.

110
111
112
113
114
115
116






































































117
118
119
120
121
122
123
124
125
126
127
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *






































































 * XCopyArea --
 *
 *	Copies data from one drawable to another using block transfer
 *	routines.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Data is moved from a window or bitmap to a second window or
 *	bitmap.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
<







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

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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
    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) {

	/* TkMacOSXDbgMsg("Drawing of emtpy area requested"); */

	return;
    }
    if (srcDraw->flags & TK_IS_PIXMAP) {
	if (!TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
	    return;
	}

	if (dc.context) {

	    CGImageRef img = TkMacOSXCreateCGImageWithDrawable(src);









	    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");
	}
	TkMacOSXRestoreDrawingContext(&dc);
    } else if (TkMacOSXDrawableWindow(src)) {
	NSView *view = TkMacOSXDrawableView(srcDraw);
	NSWindow *w = [view window];
	NSInteger gs = [w windowNumber] > 0 ? [w gState] : 0;
	/* // alternative using per-view gState:
	NSInteger gs = [view gState];
	if (!gs) {
	    [view allocateGState];
	    if ([view lockFocusIfCanDraw]) {
		[view unlockFocus];
	    }
	    gs = [view gState];
	}
	*/
	if (!gs || !TkMacOSXSetupDrawingContext(dst, gc, 1, &dc)) {
	    return;
	}
	if (dc.context) {
	    NSGraphicsContext *gc = nil;
	    CGFloat boundsH = [view bounds].size.height;
	    NSRect srcRect = NSMakeRect(srcDraw->xOff + src_x, boundsH -
		    height - (srcDraw->yOff + src_y), width, height);

	    if (((MacDrawable *) dst)->flags & TK_IS_PIXMAP) {
		gc = [NSGraphicsContext graphicsContextWithGraphicsPort:
			dc.context flipped:NO];
		if (gc) {
		    [NSGraphicsContext saveGraphicsState];
		    [NSGraphicsContext setCurrentContext:gc];
		}
	    }
	    NSCopyBits(gs, srcRect, NSMakePoint(dest_x,
		    dc.portBounds.size.height - dest_y));
	    if (gc) {
		[NSGraphicsContext restoreGraphicsState];
	    }
	} else {
	    TkMacOSXDbgMsg("Invalid destination drawable");
	}
	TkMacOSXRestoreDrawingContext(&dc);
    } else {
	TkMacOSXDbgMsg("Invalid source drawable");
    }
}

/*
 *----------------------------------------------------------------------
 *
 * XCopyPlane --
 *







>
>


>
>
>

>
|
>


|
|
|
|
>
|
>
|
>
>
>
>
|
>
>
>
>
|
|
<
|


|
|
|
|
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<







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
257
258
259
260
261
262
263
264
    unsigned long plane)	/* Which plane to copy. */
{
    TkMacOSXDrawingContext dc;
    MacDrawable *srcDraw = (MacDrawable *) src;

    display->request++;
    if (!width || !height) {
	/* TkMacOSXDbgMsg("Drawing of emtpy 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)) {







|







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
387
388
389
390
391
392
393
394
395
396
397
398
399
400
    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->obdata) {
	/*
	 * Image from XGetImage
	 */

	img = TkMacOSXCreateCGImageWithDrawable((Pixmap) image->obdata);
    } else if (image->bits_per_pixel == 1) {
	/*
	 * BW image
	 */

	static const CGFloat decodeWB[2] = {1, 0};

	bitsPerComponent = 1;







<
<
<
<
<
<
|







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
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 Macintosh GWorld.
 *
 *----------------------------------------------------------------------
 */

Pixmap
Tk_GetPixmap(
    Display *display,	/* Display for new pixmap (can be null). */







|







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
1326
1327
1328
1329
1330
1331
1332
1333
 *
 *	Release the resources associated with a pixmap.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Deletes the Macintosh GWorld created by Tk_GetPixmap.
 *
 *----------------------------------------------------------------------
 */

void
Tk_FreePixmap(
    Display *display,		/* Display. */







|







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
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;


    if (format == ZPixmap) {
	ximage->bits_per_pixel = 32;
	ximage->bitmap_unit = 32;
    } else {
	ximage->bits_per_pixel = 1;
	ximage->bitmap_unit = 8;







<









>







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
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
#else
    ximage->byte_order = LSBFirst;
    ximage->bitmap_bit_order = LSBFirst;
#endif
    ximage->red_mask = 0x00FF0000;
    ximage->green_mask = 0x0000FF00;
    ximage->blue_mask = 0x000000FF;
    ximage->obdata = NULL;
    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 image containing the data from the given
 *	rectangle of the given drawable.

 *
 * 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)
{
    MacDrawable *macDraw = (MacDrawable *) d;
    XImage *   imagePtr = NULL;
    Pixmap     pixmap = (Pixmap) NULL;
    Tk_Window  win = (Tk_Window) macDraw->winPtr;
    GC	       gc;
    char *     data = NULL;
    int	       depth = 32;
    int	       offset = 0;
    int	       bitmap_pad = 0;
    int	       bytes_per_line = 0;


    if (format == ZPixmap) {
	if (width > 0 && height > 0) {
	    /*
	     * Tk_GetPixmap fails for zero width or height.

	     */


	    pixmap = Tk_GetPixmap(display, d, width, height, depth);
	}
	if (win) {
	    XGCValues values;




	    gc = Tk_GetGC(win, 0, &values);
	} else {

	    gc = XCreateGC(display, pixmap, 0, NULL);
	}
	if (pixmap) {



	    CGContextRef context;

	    XCopyArea(display, d, pixmap, gc, x, y, width, height, 0, 0);
	    context = ((MacDrawable *) pixmap)->context;
	    if (context) {
		data = CGBitmapContextGetData(context);
		bytes_per_line = CGBitmapContextGetBytesPerRow(context);
	    }
	}
	if (data) {
	    imagePtr = XCreateImage(display, NULL, depth, format, offset,
		    data, width, height, bitmap_pad, bytes_per_line);


	    /*

	     * Track Pixmap underlying the XImage in the unused obdata field
	     * so that we can treat XImages coming from XGetImage specially.
	     */







	    imagePtr->obdata = (XPointer) pixmap;
	} else if (pixmap) {
	    Tk_FreePixmap(display, pixmap);
	}


	if (!win) {
	    XFreeGC(display, gc);



	}
    } else {
	TkMacOSXDbgMsg("Invalid image format");
    }
    return imagePtr;
}

/*
 *----------------------------------------------------------------------
 *







<


















|
|
>


















|
|
<
<
|
|
|
|
|
|
|
>

|
|
<
>
|
>
|
<
|
<
<
>

>
>
|
|
>
|

|
>
>
>
|
|
|
|
|
|
|
<
<
|
|
<
|
>
|
>
|
<
|
>
>
>
>
>
>
|
<
<
<
|
>
>
|
|
>
>
>


|







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
944
945
946
947
948
949
950
951
952
953
 */

static int
DestroyImage(
    XImage *image)
{
    if (image) {
	if (image->obdata) {
	    Tk_FreePixmap((Display*) gMacDisplay, (Pixmap) image->obdata);
	} else if (image->data) {
	    ckfree(image->data);
	}
	ckfree(image);
    }
    return 0;
}








<
<
|







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;
}