1/*
2
3Copyright 1986, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30#include "Xlibint.h"
31#include <X11/Xutil.h>		/* for XDestroyImage */
32#include "ImUtil.h"
33#include <limits.h>
34
35#define ROUNDUP(nbytes, pad) (((((nbytes) - 1) + (pad)) / (pad)) * (pad))
36
37#ifdef HAVE___BUILTIN_POPCOUNTL
38# define Ones __builtin_popcountl
39#else
40/*
41 * Count the number of bits set to 1 in a 32-bit word.
42 * Algorithm from MIT AI Lab Memo 239: "HAKMEM", ITEM 169.
43 * http://dspace.mit.edu/handle/1721.1/6086
44 */
45static inline unsigned int
46Ones(unsigned long mask)
47{
48    register unsigned long y;
49
50    y = (mask >> 1) & 033333333333;
51    y = mask - y - ((y >>1) & 033333333333);
52    return ((unsigned int) (((y + (y >> 3)) & 030707070707) % 077));
53}
54#endif
55
56XImage *XGetImage (
57     register Display *dpy,
58     Drawable d,
59     int x,
60     int y,
61     unsigned int width,
62     unsigned int height,
63     unsigned long plane_mask,
64     int format)	/* either XYPixmap or ZPixmap */
65{
66	xGetImageReply rep;
67	register xGetImageReq *req;
68	char *data;
69	unsigned long nbytes;
70	XImage *image;
71	int planes;
72	LockDisplay(dpy);
73	GetReq (GetImage, req);
74	/*
75	 * first set up the standard stuff in the request
76	 */
77	req->drawable = d;
78	req->x = x;
79	req->y = y;
80	req->width = width;
81	req->height = height;
82	req->planeMask = plane_mask;
83	req->format = format;
84
85	if (_XReply (dpy, (xReply *) &rep, 0, xFalse) == 0 ||
86	    rep.length == 0) {
87		UnlockDisplay(dpy);
88		SyncHandle();
89		return (XImage *)NULL;
90	}
91
92	if (rep.length < (INT_MAX >> 2)) {
93	    nbytes = (unsigned long)rep.length << 2;
94	    data = Xmalloc(nbytes);
95	} else
96	    data = NULL;
97	if (! data) {
98	    _XEatDataWords(dpy, rep.length);
99	    UnlockDisplay(dpy);
100	    SyncHandle();
101	    return (XImage *) NULL;
102	}
103        _XReadPad (dpy, data, nbytes);
104        if (format == XYPixmap) {
105	    image = XCreateImage(dpy, _XVIDtoVisual(dpy, rep.visual),
106		Ones (plane_mask &
107		    (((unsigned long)0xFFFFFFFF) >> (32 - rep.depth))),
108		format, 0, data, width, height, dpy->bitmap_pad, 0);
109	    planes = image->depth;
110	} else { /* format == ZPixmap */
111            image = XCreateImage (dpy, _XVIDtoVisual(dpy, rep.visual),
112		rep.depth, ZPixmap, 0, data, width, height,
113		    _XGetScanlinePad(dpy, (int) rep.depth), 0);
114	    planes = 1;
115	}
116
117	if (!image) {
118	    Xfree(data);
119	} else {
120            if (planes < 1 || image->height < 1 || image->bytes_per_line < 1 ||
121                INT_MAX / image->height <= image->bytes_per_line ||
122                INT_MAX / planes <= image->height * image->bytes_per_line ||
123                nbytes < planes * image->height * image->bytes_per_line) {
124                XDestroyImage(image);
125                image = NULL;
126            }
127	}
128	UnlockDisplay(dpy);
129	SyncHandle();
130	return (image);
131}
132
133XImage *XGetSubImage(
134     register Display *dpy,
135     Drawable d,
136     int x,
137     int y,
138     unsigned int width,
139     unsigned int height,
140     unsigned long plane_mask,
141     int format,	/* either XYPixmap or ZPixmap */
142     XImage *dest_image,
143     int dest_x,
144     int dest_y)
145{
146	XImage *temp_image;
147	temp_image = XGetImage(dpy, d, x, y, width, height,
148				plane_mask, format);
149	if (!temp_image)
150	    return (XImage *)NULL;
151	_XSetImage(temp_image, dest_image, dest_x, dest_y);
152	XDestroyImage(temp_image);
153	return (dest_image);
154}
155