Tk Source Code

Check-in [819118e2]
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 | core-8-5-branch
Files: files | file ages | folders
SHA1: 819118e223f75c0fbd1061d32aae944e1c171e28
User & Date: kevin_walzer 2014-07-07 01:09:51
Context
2014-07-24
02:30
Fix for display of images when scrolling a text widget on OS X; thanks to Marc Culler for patch check-in: 43532028 user: kevin_walzer tags: core-8-5-branch
2014-07-23
12:26
Bump to 8.5.16 for release. check-in: 26fb74c4 user: dgp tags: rc0, core-8-5-16-rc
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: 819118e2 user: kevin_walzer tags: core-8-5-branch
2014-05-27
19:33
ttk::entry, ttk::combobox: proposed fix for [a80f5d7165]: keep track of whether a drag transaction is in progress; only initiate autoscroll in <B1-Leave> if selectMode is not "none" and if %m is NotifyNormal. check-in: 6652ab5a user: jenglish tags: core-8-5-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to macosx/tkMacOSXDraw.c.

109
110
111
112
113
114
115






































































116
117
118
119
120
121
122
123
124
125
126
    }
    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.







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


|
<







109
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
    }
    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.
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
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
    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 --
 *







>
>


>
>
>

>
|
>


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


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

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







208
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
    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 --
 *
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
    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)) {







|







294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
    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)) {
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
    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;







<
<
<
<
<
<
|







424
425
426
427
428
429
430






431
432
433
434
435
436
437
438
    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.

224
225
226
227
228
229
230


231
232
233
234
235
236
237
			    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,







>
>







224
225
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 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.

805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821

822
823
824
825
826
827
828
    char* data,
    unsigned int width,
    unsigned int height,
    int bitmap_pad,
    int bytes_per_line)
{
    XImage *ximage;

    display->request++;
    ximage = (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;







<









>







805
806
807
808
809
810
811

812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
    char* data,
    unsigned int width,
    unsigned int height,
    int bitmap_pad,
    int bytes_per_line)
{
    XImage *ximage;

    display->request++;
    ximage = (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;
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






936
937
938
939
940


941
942



943
944
945
946
947
948
949
950
951
952
#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;
}

/*
 *----------------------------------------------------------------------
 *







<


















|
|
>


















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

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

>
>
|
|
>
|

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


|







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
936

937
938
939
940
941
942
943
944



945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
#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;
}

/*
 *----------------------------------------------------------------------
 *
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
 */

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((char*) image);
    }
    return 0;
}








<
<
|







974
975
976
977
978
979
980


981
982
983
984
985
986
987
988
 */

static int
DestroyImage(
    XImage *image)
{
    if (image) {


	if (image->data) {
	    ckfree(image->data);
	}
	ckfree((char*) image);
    }
    return 0;
}