diff --git a/ChangeLog b/ChangeLog index c9be428..8dc3fbb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2004-07-30 15:52 Alexander Malmberg + + * Headers/gsc/GSCStateOps.h, Source/gsc/GSContext.m, + Source/gsc/GSGState.m (-GSReadRect:): New method. + + * Source/art/GNUmakefile: Add ReadRect.m. + * Source/art/ReadRect.m: New file. + * Source/art/blit.m, Source/art/blit.h: Add read_pixels_a and + read_pixels_o. Fix spurious low bits in BLEAN_READ for 16bpp and + 15bpp modes. + + * Source/xlib/XGContext.m (-GSReadRect:): Remove. + * Source/xlib/XGGState.m (-GSReadRect:): Update key names and set all + keys even if the rectangle is degenerate. Return nil if the image + can't be read. Set the Matrix key. + 2004-07-26 15:37 Matt Rice Alexander Malmberg diff --git a/Headers/gsc/GSGStateOps.h b/Headers/gsc/GSGStateOps.h index 8737cda..b2dccf5 100644 --- a/Headers/gsc/GSGStateOps.h +++ b/Headers/gsc/GSGStateOps.h @@ -139,6 +139,8 @@ - (void) GSRectClipList: (const NSRect *)rects : (int) count; - (void) GSRectFillList: (const NSRect *)rects : (int) count; +- (NSDictionary *) GSReadRect: (NSRect)rect; + - (void)DPSimage: (NSAffineTransform*) matrix : (int) pixelsWide : (int) pixelsHigh : (int) bitsPerSample : (int) samplesPerPixel diff --git a/Source/art/GNUmakefile b/Source/art/GNUmakefile index c49a2d8..9890202 100644 --- a/Source/art/GNUmakefile +++ b/Source/art/GNUmakefile @@ -40,7 +40,8 @@ art_OBJC_FILES = \ image.m \ composite.m \ path.m \ - shfill.m + shfill.m \ + ReadRect.m -include GNUmakefile.preamble diff --git a/Source/art/ReadRect.m b/Source/art/ReadRect.m new file mode 100644 index 0000000..adc2f1e --- /dev/null +++ b/Source/art/ReadRect.m @@ -0,0 +1,139 @@ +/* + Copyright (C) 2004 Free Software Foundation, Inc. + + Author: Alexander Malmberg + + This file is part of GNUstep. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "ARTGState.h" + +#ifndef RDS +#include "x11/XWindowBuffer.h" +#endif +#include "blit.h" + +#include + +#include +#include +#include +#include + + +@implementation ARTGState (ReadRect) + +-(NSDictionary *) GSReadRect: (NSRect)r +{ + NSMutableDictionary *md = [[NSMutableDictionary alloc] init]; + NSAffineTransform *matrix; + + int x0, y0, x1, y1, w, h; + NSPoint p; + + /* Get the bounding rect in pixel coordinates. */ + p = r.origin; + p = [ctm pointInMatrixSpace: p]; + x0 = floor(p.x); x1 = ceil(p.x); + y0 = floor(p.y); y1 = ceil(p.y); + +#define CHECK do { \ + if (floor(p.x)x1) x1=ceil(p.x); \ + if (ceil(p.y)>y1) y1=ceil(p.y); } while (0) + + p = r.origin; p.x += r.size.width; + p = [ctm pointInMatrixSpace: p]; + CHECK; + + p = r.origin; p.x += r.size.width; p.y += r.size.height; + p = [ctm pointInMatrixSpace: p]; + CHECK; + + p = r.origin; p.y += r.size.height; + p = [ctm pointInMatrixSpace: p]; + CHECK; +#undef CHECK + + /* Clip to the window. */ + if (x0 < 0) x0 = 0; + if (x1 < 0) x1 = 0; + if (x0 > wi->sx) x0 = wi->sx; + if (x1 > wi->sx) x1 = wi->sx; + + if (y0 < 0) y0 = 0; + if (y1 < 0) y1 = 0; + if (y0 > wi->sy) y0 = wi->sy; + if (y1 > wi->sy) y1 = wi->sy; + + w = x1 - x0; + h = y1 - y0; + if (w <= 0 || h <= 0) + w = h = 0; + + + /* The matrix is the transform from user space to image space, and image + space has its origin in the lower left corner if the image. Thus, we need + to translate the ctm according to the position of the lower left corner + in the window. */ + matrix=[ctm copy]; + [matrix translateXBy: -x0 yBy: -y0]; + + [md setObject: NSDeviceRGBColorSpace forKey: @"ColorSpace"]; + [md setObject: [NSNumber numberWithUnsignedInt: 1] forKey: @"HasAlpha"]; + [md setObject: [NSNumber numberWithUnsignedInt: 8] forKey: @"BitsPerSample"]; + [md setObject: [NSNumber numberWithUnsignedInt: 4] forKey: @"SamplesPerPixel"]; + [md setObject: [NSValue valueWithSize: NSMakeSize(w, h)] forKey: @"Size"]; + [md setObject: matrix forKey: @"Matrix"]; + [matrix release]; + + if (!w || !h) + return [[md autorelease] makeImmutableCopyOnFail: YES]; + + /* The rectangle isn't degenerate, so we need to actually copy some data. */ + { + NSMutableData *d; + int y; + composite_run_t c; + + d = [[NSMutableData alloc] initWithLength: w * h * 4]; + + c.dst = [d mutableBytes]; + + c.src = wi->data + (wi->sy - y1) * wi->bytes_per_line + x0 * DI.bytes_per_pixel; + c.srca = wi->alpha + (wi->sy - y1) * wi->sx + x0; + + for (y = 0; y < h; y++) + { + if (wi->has_alpha) + DI.read_pixels_a(&c, w); + else + DI.read_pixels_o(&c, w); + c.src += wi->bytes_per_line; + c.srca += wi->sx; + c.dst += w * 4; + } + + [md setObject: [[d autorelease] makeImmutableCopyOnFail: YES] forKey: @"Data"]; + } + + return [[md autorelease] makeImmutableCopyOnFail: YES]; +} + +@end + diff --git a/Source/art/blit.h b/Source/art/blit.h index 0bee37f..8b32c4d 100644 --- a/Source/art/blit.h +++ b/Source/art/blit.h @@ -100,6 +100,11 @@ typedef struct draw_info_s int num); + /* dst should be a 32bpp RGBA buffer. */ + void (*read_pixels_o)(composite_run_t *c, int num); + void (*read_pixels_a)(composite_run_t *c, int num); + + void (*composite_sover_aa)(composite_run_t *c, int num); void (*composite_sover_ao)(composite_run_t *c, int num); diff --git a/Source/art/blit.m b/Source/art/blit.m index 15345f9..b22cc01 100644 --- a/Source/art/blit.m +++ b/Source/art/blit.m @@ -456,6 +456,46 @@ static void MPRE(run_opaque_a) (render_run_t *ri, int num) } +static void MPRE(read_pixels_o) (composite_run_t *c, int num) +{ + BLEND_TYPE *s = (BLEND_TYPE *)c->src; + unsigned char *dst = c->dst; + int r, g, b; + + for (; num; num--) + { + BLEND_READ(s, r, g, b) + BLEND_INC(s) + dst[0] = r; + dst[1] = g; + dst[2] = b; + dst[3] = 0xff; + dst += 4; + } +} + +static void MPRE(read_pixels_a) (composite_run_t *c, int num) +{ + BLEND_TYPE *s = (BLEND_TYPE *)c->src; +#ifndef INLINE_ALPHA + unsigned char *src_alpha = c->srca; +#endif + unsigned char *dst = c->dst; + int r, g, b, a; + + for (; num; num--) + { + BLEND_READ_ALPHA(s, src_alpha, r, g, b, a) + ALPHA_INC(s, src_alpha) + dst[0] = r; + dst[1] = g; + dst[2] = b; + dst[3] = a; + dst += 4; + } +} + + /* 1 : 1 - srca */ static void MPRE(sover_aa) (composite_run_t *c, int num) { @@ -1683,8 +1723,8 @@ ourself. #define BLEND_READ(p,nr,ng,nb) \ { \ unsigned short _s=p[0]; \ - nr=(_s>>8); \ - ng=(_s>>3)&0xff; \ + nr=(_s>>11)<<3; \ + ng=((_s>>5)<<2)&0xff; \ nb=(_s<<3)&0xff; \ } #define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) \ @@ -1721,8 +1761,8 @@ ourself. #define BLEND_READ(p,nr,ng,nb) \ { \ unsigned short _s=p[0]; \ - nr=(_s>>7); \ - ng=(_s>>2)&0xff; \ + nr=(_s>>10)<<3; \ + ng=((_s>>5)<<3)&0xff; \ nb=(_s<<3)&0xff; \ } #define BLEND_READ_ALPHA(p,pa,nr,ng,nb,na) \ @@ -1768,6 +1808,9 @@ static draw_info_t draw_infos[DI_NUM] = { \ NPRE(blit_subpixel,x), \ \ + NPRE(read_pixels_o,x), \ + NPRE(read_pixels_a,x), \ + \ NPRE(sover_aa,x), \ NPRE(sover_ao,x), \ NPRE(sin_aa,x), \ diff --git a/Source/gsc/GSContext.m b/Source/gsc/GSContext.m index a1f4dca..7085878 100644 --- a/Source/gsc/GSContext.m +++ b/Source/gsc/GSContext.m @@ -781,6 +781,12 @@ static unsigned int unique_index = 0; /* NSGraphics Ops */ /* ----------------------------------------------------------------------- */ @implementation GSContext (NSGraphics) + +- (NSDictionary *) GSReadRect: (NSRect)rect +{ + return [gstate GSReadRect: rect]; +} + /* * Render Bitmap Images */ diff --git a/Source/gsc/GSGState.m b/Source/gsc/GSGState.m index 7458ead..03d4798 100644 --- a/Source/gsc/GSGState.m +++ b/Source/gsc/GSGState.m @@ -1007,6 +1007,11 @@ typedef enum { : NSWidth(rects[i]) : NSHeight(rects[i])]; } +- (NSDictionary *) GSReadRect: (NSRect)r +{ + return nil; +} + - (void)DPSimage: (NSAffineTransform*) matrix : (int) pixelsWide : (int) pixelsHigh : (int) bitsPerSample : (int) samplesPerPixel diff --git a/Source/xlib/XGContext.m b/Source/xlib/XGContext.m index 75d5baa..25af357 100644 --- a/Source/xlib/XGContext.m +++ b/Source/xlib/XGContext.m @@ -153,11 +153,6 @@ XFlush([(XGServer *)server xDisplay]); } -- (NSDictionary *) GSReadRect: (NSRect)rect -{ - return [(XGGState *)gstate GSReadRect: rect]; -} - @end @implementation XGContext (Ops) diff --git a/Source/xlib/XGGState.m b/Source/xlib/XGGState.m index 514e91b..9f58497 100644 --- a/Source/xlib/XGGState.m +++ b/Source/xlib/XGGState.m @@ -1715,6 +1715,7 @@ static Region emptyRegion; gswindow_device_t *source_win; NSMutableDictionary *dict; NSData *data; + NSAffineTransform *matrix; source_win = (gswindow_device_t *)windevice; if (!source_win) @@ -1739,22 +1740,41 @@ static Region emptyRegion; srect = XGIntersectionRect (srect, accessibleRectForWindow (source_win)); ssize.width = srect.width; ssize.height = srect.height; - [dict setObject: [NSValue valueWithSize: ssize] forKey: @"ImageSize"]; + [dict setObject: [NSValue valueWithSize: ssize] forKey: @"Size"]; + + [dict setObject: NSDeviceRGBColorSpace forKey: @"ColorSpace"]; + [dict setObject: [NSNumber numberWithUnsignedInt: 8] forKey: @"BitsPerSample"]; + [dict setObject: [NSNumber numberWithUnsignedInt: source_win->depth] + forKey: @"Depth"]; + [self _alphaBuffer: source_win]; + if (alpha_buffer) + { + [dict setObject: [NSNumber numberWithUnsignedInt: 4] + forKey: @"SamplesPerPixel"]; + [dict setObject: [NSNumber numberWithUnsignedInt: 1] + forKey: @"HasAlpha"]; + } + else + { + [dict setObject: [NSNumber numberWithUnsignedInt: 3] + forKey: @"SamplesPerPixel"]; + [dict setObject: [NSNumber numberWithUnsignedInt: 0] + forKey: @"HasAlpha"]; + } + matrix = [ctm copy]; + [matrix translateXBy: -srect.x - offset.x yBy: srect.y + srect.height - offset.y]; + [dict setObject: matrix forKey: @"Matrix"]; + DESTROY(matrix); 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)); + /* Non-backingstore window isn't visible, so we can't read it. */ + return nil; } else { @@ -1765,36 +1785,24 @@ static Region emptyRegion; if (source_im->image == 0) { // Should not happen, - DPS_ERROR (DPSinvalidaccess, @"unable to fetch source image"); - return dict; + return nil; } - [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"]; + [dict setObject: data forKey: @"Data"]; /* Pixmap routine always returns image in same format (FIXME?). */ - [dict setObject: NSDeviceRGBColorSpace forKey: @"ImageColorSpace"]; - [dict setObject: [NSNumber numberWithUnsignedInt: 8] forKey: @"ImageBPS"]; // --- clean up ------------------------------------------------------