1/*
2   Copyright (C) 2004 Free Software Foundation, Inc.
3
4   Author:  Alexander Malmberg <alexander@malmberg.org>
5
6   This file is part of GNUstep.
7
8   This library is free software; you can redistribute it and/or
9   modify it under the terms of the GNU Lesser General Public
10   License as published by the Free Software Foundation; either
11   version 2 of the License, or (at your option) any later version.
12
13   This library is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public
19   License along with this library; see the file COPYING.LIB.
20   If not, see <http://www.gnu.org/licenses/> or write to the
21   Free Software Foundation, 51 Franklin Street, Fifth Floor,
22   Boston, MA 02110-1301, USA.
23*/
24
25#include "ARTGState.h"
26
27#ifndef RDS
28#include "x11/XWindowBuffer.h"
29#endif
30#include "blit.h"
31
32#include <math.h>
33
34#include <Foundation/NSData.h>
35#include <Foundation/NSDictionary.h>
36#include <Foundation/NSValue.h>
37#include <AppKit/NSAffineTransform.h>
38#include <AppKit/NSGraphics.h>
39
40
41@implementation ARTGState (ReadRect)
42
43-(NSDictionary *) GSReadRect: (NSRect)r
44{
45  NSMutableDictionary *md = [[NSMutableDictionary alloc] init];
46  NSAffineTransform *matrix;
47
48  int x0, y0, x1, y1, w, h, ox, oy;
49  NSPoint p;
50
51  /* Get the bounding rect in pixel coordinates. */
52  p = r.origin;
53  p = [ctm transformPoint: p];
54  x0 = floor(p.x);  x1 = ceil(p.x);
55  y0 = floor(p.y);  y1 = ceil(p.y);
56
57#define CHECK do { \
58  if (floor(p.x)<x0) x0=floor(p.x); \
59  if (floor(p.y)<y0) y0=floor(p.y); \
60  if (ceil(p.x)>x1) x1=ceil(p.x); \
61  if (ceil(p.y)>y1) y1=ceil(p.y); } while (0)
62
63  p = r.origin; p.x += r.size.width;
64  p = [ctm transformPoint: p];
65  CHECK;
66
67  p = r.origin; p.x += r.size.width; p.y += r.size.height;
68  p = [ctm transformPoint: p];
69  CHECK;
70
71  p = r.origin; p.y += r.size.height;
72  p = [ctm transformPoint: p];
73  CHECK;
74#undef CHECK
75
76  /* Clip to the window. */
77  if (x0 < 0) x0 = 0;
78  if (x1 < 0) x1 = 0;
79  if (x0 > wi->sx) x0 = wi->sx;
80  if (x1 > wi->sx) x1 = wi->sx;
81
82  if (y0 < 0) y0 = 0;
83  if (y1 < 0) y1 = 0;
84  if (y0 > wi->sy) y0 = wi->sy;
85  if (y1 > wi->sy) y1 = wi->sy;
86
87  w = x1 - x0;
88  h = y1 - y0;
89  if (w <= 0 || h <= 0)
90    w = h = 0;
91
92
93  /* The matrix is the transform from user space to image space, and image
94  space has its origin in the lower left corner if the image. Thus, we need
95  to translate the ctm according to the position of the lower left corner
96  in the window. */
97  matrix=[ctm copy];
98  [matrix translateXBy: -x0 yBy: -y0];
99
100  ox = [matrix transformPoint: NSMakePoint(0, 0)].x - offset.x;
101  oy = offset.y - [matrix transformPoint: NSMakePoint(0, 0)].y;
102
103  [md setObject: NSDeviceRGBColorSpace  forKey: @"ColorSpace"];
104  [md setObject: [NSNumber numberWithUnsignedInt: 1]  forKey: @"HasAlpha"];
105  [md setObject: [NSNumber numberWithUnsignedInt: 8]  forKey: @"BitsPerSample"];
106  [md setObject: [NSNumber numberWithUnsignedInt: 4]  forKey: @"SamplesPerPixel"];
107  [md setObject: [NSValue valueWithSize: NSMakeSize(w, h)]  forKey: @"Size"];
108  [md setObject: matrix  forKey: @"Matrix"];
109  [matrix release];
110
111  if (!w || !h)
112    return [[md autorelease] makeImmutableCopyOnFail: YES];
113
114  /* The rectangle isn't degenerate, so we need to actually copy some data. */
115  {
116    NSMutableData *d;
117    int y;
118    composite_run_t c;
119
120    d = [[NSMutableData alloc] initWithLength: w * h * 4];
121
122    c.dst = [d mutableBytes];
123
124    c.src = wi->data + (oy - y1) * wi->bytes_per_line + (x0 + ox) * DI.bytes_per_pixel;
125    c.srca = wi->alpha + (oy - y1) * wi->sx + (x0 + ox);
126
127    for (y = 0; y < h; y++)
128      {
129	if (wi->has_alpha)
130	  DI.read_pixels_a(&c, w);
131	else
132	  DI.read_pixels_o(&c, w);
133	c.src += wi->bytes_per_line;
134	c.srca += wi->sx;
135	c.dst += w * 4;
136      }
137
138    [md setObject: [[d autorelease] makeImmutableCopyOnFail: YES]  forKey: @"Data"];
139  }
140
141  return [[md autorelease] makeImmutableCopyOnFail: YES];
142}
143
144@end
145
146