2003-09-15 Adam Fedor * Headers/xlib/XGGState.h: Add GSReadRect def. * Headers/xlib/XGPrivate.h: Add _pixmap_read_alpha def. * Source/xlib/XGBitmap.m (_pixmap_read_alpha): Implement. * Source/xlib/XGGstate.m (-GSReadRect:): Idem. Index: Headers/xlib/XGGState.h =================================================================== RCS file: /cvsroot/gnustep/gnustep/core/back/Headers/xlib/XGGState.h,v retrieving revision 1.5 diff -u -p -r1.5 XGGState.h --- Headers/xlib/XGGState.h 10 May 2002 15:06:17 -0000 1.5 +++ Headers/xlib/XGGState.h 16 Sep 2003 03:26:01 -0000 @@ -72,5 +72,9 @@ @end +@interface XGGState (Ops) +- (NSDictionary *) GSReadRect: (NSRect)rect; +@end + #endif /* _XGGState_h_INCLUDE */ Index: Headers/xlib/XGPrivate.h =================================================================== RCS file: /cvsroot/gnustep/gnustep/core/back/Headers/xlib/XGPrivate.h,v retrieving revision 1.6 diff -u -p -r1.6 XGPrivate.h --- Headers/xlib/XGPrivate.h 31 Jul 2003 23:57:10 -0000 1.6 +++ Headers/xlib/XGPrivate.h 16 Sep 2003 03:26:01 -0000 @@ -102,6 +102,10 @@ extern int _bitmap_combine_alpha(RContex NSCompositingOperation op, XGDrawMechanism drawMechanism); +extern NSData *_pixmap_read_alpha(RContext *context, + RXImage *source_im, RXImage *source_alpha, + XRectangle srect, + XGDrawMechanism drawMechanism); #endif Index: Source/xlib/XGBitmap.m =================================================================== RCS file: /cvsroot/gnustep/gnustep/core/back/Source/xlib/XGBitmap.m,v retrieving revision 1.4 diff -u -p -r1.4 XGBitmap.m --- Source/xlib/XGBitmap.m 3 Aug 2002 03:32:19 -0000 1.4 +++ Source/xlib/XGBitmap.m 16 Sep 2003 03:26:05 -0000 @@ -37,6 +37,7 @@ #include #include +#include #include #include "gsc/gscolors.h" #include "xlib/XGPrivate.h" @@ -1137,3 +1138,128 @@ _bitmap_combine_alpha(RContext *context, } return 0; } + +NSData * +_pixmap_read_alpha(RContext *context, + RXImage *source_im, RXImage *source_alpha, + XRectangle srect, + XGDrawMechanism drawMechanism) +{ + unsigned long pixel; + NSMutableData *data; + unsigned char *bytes; + int spp; + + spp = (source_alpha) ? 4 : 3; + data = [NSMutableData dataWithLength: srect.width*srect.height*spp]; + if (data == nil) + return nil; + bytes = [data mutableBytes]; + + if (drawMechanism == XGDM_FAST15 + || drawMechanism == XGDM_FAST16 + || drawMechanism == XGDM_FAST32 + || drawMechanism == XGDM_FAST32_BGR) + { + VARIABLES_DECLARATION; + unsigned row; + + switch (drawMechanism) + { + case XGDM_FAST15: + InitRGBShiftsAndMasks(10,5,5,5,0,5,0,8); + break; + case XGDM_FAST16: + InitRGBShiftsAndMasks(11,5,5,6,0,5,0,8); + break; + case XGDM_FAST32: + InitRGBShiftsAndMasks(16,8,8,8,0,8,0,8); + break; + case XGDM_FAST32_BGR: + InitRGBShiftsAndMasks(0,8,8,8,16,8,0,8); + break; + default: + NSLog(@"Huh? Backend confused about XGDrawMechanism"); + //Try something. With a bit of luck we see + //which picture goes wrong. + InitRGBShiftsAndMasks(11,5,5,6,0,5,0,8); + } + + for (row = 0; row < srect.height; row++) + { + unsigned col; + + for (col = 0; col < srect.width; col++) + { + unsigned sr, sg, sb, sa; + + // Get the source pixel information + pixel = XGetPixel(source_im->image, col, row); + PixelToRGB(pixel, sr, sg, sb); + // Expand to 8 bit value + sr = (sr << (8-_rwidth)); + sg = (sg << (8-_gwidth)); + sb = (sb << (8-_bwidth)); + + if (source_alpha) + { + pixel = XGetPixel(source_alpha->image, col, row); + sa = (pixel >> _ashift) & _amask; + } + else + sa = _amask; + + bytes[(row * srect.width + col)*spp] = sr; + bytes[(row * srect.width + col)*spp+1] = sg; + bytes[(row * srect.width + col)*spp+2] = sb; + if (source_alpha) + bytes[(row * srect.width + col)*spp+3] = sa; + } + } + } + else + { + XColor c2; + unsigned row; + + /* + * This block of code should be totally portable as it uses the + * 'official' X mechanism for converting from pixel values to + * RGB color values - on the downside, it's very slow. + */ + pixel = (unsigned long)-1; // Never valid? + c2.pixel = pixel; + + for (row = 0; row < srect.height; row++) + { + unsigned col; + + for (col = 0; col < srect.width; col++) + { + int r, g, b, alpha; + XColor pcolor, acolor; + pcolor.pixel = XGetPixel(source_im->image, col, row); + XQueryColor(context->dpy, context->cmap, &pcolor); + r = pcolor.red >> 8; + g = pcolor.green >> 8; + b = pcolor.blue >> 8; + alpha = 255; + if (source_alpha) + { + acolor.pixel = XGetPixel(source_alpha->image, col, row); + XQueryColor(context->dpy, context->cmap, &acolor); + alpha = acolor.red >> 8; + } + + bytes[(row * srect.width + col)*spp] = r; + bytes[(row * srect.width + col)*spp+1] = g; + bytes[(row * srect.width + col)*spp+2] = b; + if (source_alpha) + bytes[(row * srect.width + col)*spp+3] = alpha; + } + } + } + + return (NSData *)data; +} + Index: Source/xlib/XGContext.m =================================================================== RCS file: /cvsroot/gnustep/gnustep/core/back/Source/xlib/XGContext.m,v retrieving revision 1.10 diff -u -p -r1.10 XGContext.m --- Source/xlib/XGContext.m 24 Jul 2003 03:24:13 -0000 1.10 +++ Source/xlib/XGContext.m 16 Sep 2003 03:26:05 -0000 @@ -153,13 +153,9 @@ XFlush([(XGServer *)server xDisplay]); } -// -// Read the Color at a Screen Position -// -- (NSColor *) NSReadPixel: (NSPoint) location +- (NSDictionary *) GSReadRect: (NSRect)rect { - [self notImplemented: _cmd]; - return nil; + return [(XGGState *)gstate GSReadRect: rect]; } @end Index: Source/xlib/XGGState.m =================================================================== RCS file: /cvsroot/gnustep/gnustep/core/back/Source/xlib/XGGState.m,v retrieving revision 1.17 diff -u -p -r1.17 XGGState.m --- Source/xlib/XGGState.m 17 Jun 2003 13:34:38 -0000 1.17 +++ Source/xlib/XGGState.m 16 Sep 2003 03:26:10 -0000 @@ -1857,6 +1857,103 @@ typedef enum { } } +- (NSDictionary *) GSReadRect: (NSRect)rect +{ + NSSize ssize; + XRectangle srect; + RXImage *source_im; + RXImage *source_alpha; + gswindow_device_t *source_win; + NSMutableDictionary *dict; + NSData *data; + + source_win = (gswindow_device_t *)windevice; + if (!source_win) + { + DPS_ERROR(DPSinvalidid, @"Invalid read gstate"); + return nil; + } + + if (source_win->buffer == 0 && source_win->map_state != IsViewable) + { + /* Can't read anything */ + DPS_ERROR(DPSinvalidid, @"Invalid window not readable"); + return nil; + } + + dict = [NSMutableDictionary dictionary]; + + // --- determine region to read -------------------------------------- + + rect.origin = [ctm pointInMatrixSpace: rect.origin]; + srect = XGWindowRectToX(self, rect); + srect = XGIntersectionRect (srect, accessibleRectForWindow (source_win)); + ssize.width = srect.width; + ssize.height = srect.height; + [dict setObject: [NSValue valueWithSize: ssize] forKey: @"ImageSize"]; + + if (XGIsEmptyRect(srect)) + return dict; + + [dict setObject: [NSNumber numberWithUnsignedInt: source_win->depth] + forKey: @"ImageDepth"]; + + // --- get source XImage ---------------------------------------- + + if (draw == source_win->ident && source_win->visibility < 0) + { + /* Non-backingstore window isn't visible, so just make up the image */ + NSLog(@"Focused view window not readable"); + source_im = RCreateXImage(context, source_win->depth, + XGWidth(srect), XGHeight(srect)); + } + else + { + source_im = RGetXImage(context, draw, XGMinX(srect), XGMinY (srect), + XGWidth (srect), XGHeight (srect)); + } + + if (source_im->image == 0) + { + // Should not happen, + DPS_ERROR (DPSinvalidaccess, @"unable to fetch source image"); + return dict; + } + + [self _alphaBuffer: source_win]; + if (alpha_buffer) + { + source_alpha = RGetXImage((RContext *)context, alpha_buffer, + XGMinX(srect), XGMinY(srect), + XGWidth(srect), XGHeight(srect)); + [dict setObject: [NSNumber numberWithUnsignedInt: 4] + forKey: @"ImageSPP"]; + [dict setObject: [NSNumber numberWithUnsignedInt: 1] + forKey: @"ImageAlpha"]; + } + else + { + source_alpha = NULL; + [dict setObject: [NSNumber numberWithUnsignedInt: 3] + forKey: @"ImageSPP"]; + [dict setObject: [NSNumber numberWithUnsignedInt: 0] + forKey: @"ImageAlpha"]; + } + + data = _pixmap_read_alpha(context, source_im, source_alpha, srect, + drawMechanism); + [dict setObject: data forKey: @"ImageData"]; + /* Pixmap routine always returns image in same format (FIXME?). */ + [dict setObject: NSDeviceRGBColorSpace forKey: @"ImageColorSpace"]; + [dict setObject: [NSNumber numberWithUnsignedInt: 8] forKey: @"ImageBPS"]; + + // --- clean up ------------------------------------------------------ + + RDestroyXImage((RContext *)context, source_im); + RDestroyXImage((RContext *)context, source_alpha); + return dict; +} + @end