|
|
1.1 root 1: #include "copyright.h"
2:
3: /* $Header: XPutImage.c,v 11.34 87/09/11 15:46:16 rws Exp $ */
4: /* Copyright Massachusetts Institute of Technology 1986 */
5:
6: #include <stdio.h>
7: #include "Xlibint.h"
8: #include <errno.h>
9:
10:
11: #define ROUNDUP(nbytes, pad) (((((nbytes) - 1) + (pad)) / (pad)) * (pad))
12:
13: /* XXX Note to who ever must maintain this code:
14:
15: The helper routine "PutImageRequest" is unfinished and still has a few bugs.
16: Byte swapping is never required when
17: (image->byte_order == image->bitmap_bit_order) &&
18: (dpy->byte_order == dpy->bitmap_bit_order)
19: Someday we will write a treatise on the subject. If you don't believe us, try it.
20: Note that all display hardware we know of works this way.
21: Note that in X10, shipping from a VAX to a SUN ended up byte-swapping twice (once
22: in dix and once in ddx). Shipping from a SUN to a VAX byte-swapped once, but
23: that worked because bitmaps were described as shorts in VAX order, and thus when
24: compiled on a SUN resulted in the additional byte-swap.
25:
26: Swapping in the other cases is probably worked out, but we don't have time to
27: make sure, and we don't have any machines that do things that way to test it on.
28: You probably need to swap halves within longs without swapping bytes within shorts
29: for some cases.
30:
31: Also, if a client sends ZPixmap format images of 4 bits_per_pixel and nibble swapping
32: is required, this routine does not swap the 4 bit nibbles as it should.
33:
34: XXX */
35:
36: static PutImageRequest(dpy, d, gc, image, req_xoffset,req_yoffset, x, y, req_width,
37: req_height)
38: register Display *dpy;
39: Drawable d;
40: GC gc;
41: register XImage *image;
42: int x, y;
43: unsigned int req_width, req_height;
44: int req_xoffset, req_yoffset;
45: {
46: register xPutImageReq *req;
47: int total_xoffset;
48:
49: FlushGC(dpy, gc);
50: GetReq (PutImage, req);
51: /*
52: * first set up the standard stuff in the request
53: */
54: req->drawable = d;
55: req->gc = gc->gid;
56: req->dstX = x;
57: req->dstY = y;
58: req->width = req_width;
59: req->height = req_height;
60: req->format = image->format;
61: req->depth = image->depth;
62: total_xoffset = image->xoffset + req_xoffset;
63: switch (image->format) {
64: long length;
65: int i;
66: case XYBitmap:
67: /*
68: * If the client side format matches the screen, we win!
69: */
70: if ((dpy->bitmap_unit == image->bitmap_unit)
71: &&(dpy->bitmap_pad == image->bitmap_pad)
72: &&(dpy->byte_order == image->byte_order)
73: &&(dpy->bitmap_bit_order == image->bitmap_bit_order)
74: &&(image->width == req_width)
75: &&(total_xoffset < dpy->bitmap_pad)
76: &&(req_yoffset == 0)) {
77: length = image->bytes_per_line * req_height;
78: req->length += length >> 2;
79: req->leftPad = total_xoffset;
80: _XSend (dpy, image->data, length);
81: }
82: else {
83: long nbytes;
84: char *row_addr;
85: register char *p;
86: char* tempbuf;
87: /*
88: * compute length of image data; round up to next length
89: */
90: req->leftPad = total_xoffset%dpy->bitmap_pad;
91: nbytes = length = ROUNDUP(req_width + req->leftPad,
92: dpy->bitmap_pad) >> 3;
93: length *= req_height;
94: req->length += length >> 2;
95:
96: /*Get space to put the image*/
97:
98: tempbuf = p = _XAllocScratch (dpy,
99: (unsigned long)(length));
100:
101: /*Figure out where to start*/
102:
103: row_addr = (image->data)+
104: (image->bytes_per_line*req_yoffset) +
105: ((total_xoffset - req->leftPad)>>3);
106:
107: /* Now copy the desired (sub)image into the buffer */
108:
109: for (i = 0; i < req_height;
110: i++, row_addr += image->bytes_per_line,p+=nbytes) {
111: bcopy (row_addr, p, (int)nbytes);
112: if (image->bitmap_bit_order
113: != dpy->bitmap_bit_order) _swapbits (
114: (unsigned char *)p, image->bytes_per_line);
115: #ifdef notdef
116: if ((image->byte_order != image->bitmap_bit_order) ||
117: (dpy->byte_order != dpy->bitmap_bit_order))
118: {
119: /* XXX swapping missing XXX */
120: }
121: #endif
122: }
123: _XSend(dpy,tempbuf,length);
124: }
125:
126: break;
127:
128: case XYPixmap: /* not yet implemented */
129: /*
130: * If the client side format matches the screen, we win!
131: */
132: if ((dpy->bitmap_unit == image->bitmap_unit)
133: &&(dpy->bitmap_pad == image->bitmap_pad)
134: &&(dpy->byte_order == image->byte_order)
135: &&(dpy->bitmap_bit_order == image->bitmap_bit_order)
136: &&(image->width == req_width)
137: &&(total_xoffset < dpy->bitmap_pad)
138: &&(req_yoffset == 0)) {
139: length = image->bytes_per_line * req_height *
140: image->depth;
141: req->length += length >> 2;
142: req->leftPad = total_xoffset;
143: _XSend (dpy, image->data, length);
144: }
145: else {
146: long nbytes;
147: char *row_addr;
148: register char *p;
149: char* tempbuf;
150: int bytes_per_plane,j;
151: /*
152: * compute length of image data; round up to next length
153: */
154: req->leftPad = total_xoffset%dpy->bitmap_pad;
155: nbytes = length = ROUNDUP(req_width + req->leftPad,
156: dpy->bitmap_pad) >> 3;
157: length *= req_height * image->depth;
158: req->length += length >> 2;
159: bytes_per_plane = image->bytes_per_line * image->height;
160:
161: /*Get space to put the image*/
162:
163: tempbuf = p = _XAllocScratch (dpy,
164: (unsigned long)(length));
165:
166: /* Loop on planes */
167:
168: for (j = 0; j < image->depth; j++) {
169:
170: /*Figure out where to start in image structure*/
171:
172: row_addr = (image->data)+
173: (j * bytes_per_plane) +
174: (image->bytes_per_line*req_yoffset) +
175: ((total_xoffset - req->leftPad)>>3);
176:
177: /* Now copy a plane of the desired (sub)image into the
178: buffer */
179:
180: for (i = 0; i < req_height;
181: i++, row_addr += image->bytes_per_line,p+=nbytes) {
182: bcopy (row_addr, p, (int)nbytes);
183: if (image->bitmap_bit_order
184: != dpy->bitmap_bit_order) _swapbits (
185: (unsigned char *)p, nbytes);
186: #ifdef notdef
187: if ((image->byte_order != image->bitmap_bit_order) ||
188: (dpy->byte_order != dpy->bitmap_bit_order))
189: {
190: /* XXX swapping missing XXX */
191: }
192: #endif
193: }
194: }
195: _XSend(dpy,tempbuf,length);
196: }
197:
198: break;
199:
200: case ZPixmap:
201: /*
202: * If the client side format matches the screen, we win!
203: */
204: /* XXX is this right? */
205: req->leftPad = 0;
206:
207: if ((dpy->byte_order == image->byte_order)
208: &&(dpy->bitmap_pad == image->bitmap_pad)) {
209: length = image->bytes_per_line * image->height;
210: req->length += length >> 2;
211: _XSend (dpy, image->data, length);
212: }
213: else {
214: /*
215: * since we have no other way to go, we presume format
216: * of image matches format of drawable.... Sure makes
217: * things simpler.
218: */
219: long nbytes;
220: unsigned char *row = (unsigned char *) (image->data + req_yoffset * image->bytes_per_line);
221: unsigned char *tempbuf, *p;
222: int bit_xoffset, pseudoLeftPad, byte_xoffset;
223: int j;
224:
225: nbytes = length = ROUNDUP(req_width * image->bits_per_pixel, dpy->bitmap_pad) >> 3;
226:
227: tempbuf = p = (unsigned char *)_XAllocScratch(dpy, (unsigned long)nbytes * req_height);
228:
229: length *= req_height;
230: req->length += length >> 2;
231:
232: bit_xoffset = req_xoffset * image->bits_per_pixel;
233: pseudoLeftPad = bit_xoffset % 8;
234: byte_xoffset = bit_xoffset >> 3;
235:
236: for (i = 0; i < req_height;
237: i++, row += image->bytes_per_line, p+=nbytes) {
238: /*
239: * Move the data somewhere we can reformat it.
240: */
241:
242:
243: if (pseudoLeftPad != 0)
244: {
245: for ( j=0; j < nbytes; j++)
246: {
247: p[j] = (row[byte_xoffset + j] >> (pseudoLeftPad)) | (row[byte_xoffset + j + 1] << ( 8 - pseudoLeftPad));
248: }
249:
250: }
251: else
252: bcopy (row + ((req_xoffset * image->bits_per_pixel) >> 3), p, (int)nbytes);
253: if (image->byte_order != dpy->byte_order) {
254: if(image->bits_per_pixel == 32) _swaplong(p, nbytes);
255: else if (image->bits_per_pixel == 24)
256: _swapthree (p, nbytes);
257: else if (image->bits_per_pixel == 16)
258: _swapshort (p, nbytes);
259: }
260: }
261: _XSend(dpy, tempbuf, length);
262: }
263: break;
264: default: /* should never get here */
265: (void) fputs ("unknown image type in XPutImage\n", stderr);
266: exit(1);
267: break;
268: }
269:
270: SyncHandle();
271: return;
272: }
273:
274:
275: char _reverse_byte[0x100] = {
276: 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
277: 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
278: 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
279: 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
280: 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
281: 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
282: 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
283: 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
284: 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
285: 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
286: 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
287: 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
288: 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
289: 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
290: 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
291: 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
292: 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
293: 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
294: 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
295: 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
296: 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
297: 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
298: 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
299: 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
300: 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
301: 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
302: 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
303: 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
304: 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
305: 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
306: 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
307: 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
308: };
309:
310:
311: _swapbits (b, n)
312: register unsigned char *b;
313: register long n;
314: {
315: do {
316: *b = _reverse_byte[*b];
317: b++;
318: } while (--n > 0);
319:
320: }
321:
322: _swapshort (bp, n)
323: register char *bp;
324: register long n;
325: {
326: register char c;
327: register char *ep = bp + n;
328: do {
329: c = *bp;
330: *bp = *(bp + 1);
331: bp++;
332: *bp = c;
333: bp++;
334: }
335: while (bp < ep);
336: }
337:
338: _swaplong (bp, n)
339: register char *bp;
340: register long n;
341: {
342: register char c;
343: register char *ep = bp + n;
344: register char *sp;
345: do {
346: sp = bp + 3;
347: c = *sp;
348: *sp = *bp;
349: *bp++ = c;
350: sp = bp + 1;
351: c = *sp;
352: *sp = *bp;
353: *bp++ = c;
354: bp += 2;
355: }
356: while (bp < ep);
357: }
358:
359: _swapthree (bp, n)
360: register char *bp;
361: register long n;
362: {
363: register char c;
364: register char *ep = bp + n;
365: do {
366: c = *bp;
367: *(bp + 2) = *bp;
368: *bp = c;
369: bp += 3;
370: }
371: while (bp < ep);
372: }
373:
374:
375: static int
376: BytesPerImageRow(dpy, image, req_width, req_xoffset)
377: Display *dpy;
378: XImage *image;
379: unsigned int req_width;
380: int req_xoffset;
381: {
382: int total_offset = image->xoffset + req_xoffset;
383: int left_pad = total_offset % dpy->bitmap_pad;
384: int nbytes;
385:
386: switch (image->format)
387: {
388: case XYBitmap:
389: nbytes = ROUNDUP(req_width + left_pad, dpy->bitmap_pad) >> 3;
390: break;
391:
392: case XYPixmap:
393: nbytes = (ROUNDUP(req_width + left_pad, dpy->bitmap_pad) >> 3)
394: * image->depth;
395: break;
396: case ZPixmap:
397: nbytes = ROUNDUP(req_width * image->bits_per_pixel,
398: dpy->bitmap_pad) >> 3;
399: break;
400: default: /* should never get here */
401: (void) fputs ("unknown image type in XPutImage\n", stderr);
402: exit(1);
403: break;
404: }
405:
406: return nbytes;
407: }
408:
409: static void
410: PutSubImage (dpy, d, gc, image, req_xoffset,req_yoffset, x, y, req_width,
411: req_height)
412: register Display *dpy;
413: Drawable d;
414: GC gc;
415: register XImage *image;
416: int x, y;
417: unsigned int req_width, req_height;
418: int req_xoffset, req_yoffset;
419:
420: {
421: int total_offset = image->xoffset + req_xoffset;
422: int left_pad = total_offset % dpy->bitmap_pad;
423: int BytesPerRowOfImage;
424: int BytesInRequestAvailableForImage;
425: int MaximumRequestSizeInBytes =
426: (65536 < dpy->max_request_size) ? (65536 << 2)
427: :( dpy->max_request_size << 2);
428:
429: if ((req_width == 0) || (req_height == 0)) return;
430:
431: BytesInRequestAvailableForImage = MaximumRequestSizeInBytes -
432: sizeof(xPutImageReq);
433:
434: if (BytesInRequestAvailableForImage < (dpy->bitmap_pad >> 3))
435: {
436: /* This is a ridiculous case that should never happen, but just in
437: case. */
438: (void) fputs("Request size is simply too small to put image\n",
439: stderr);
440: exit(1);
441: }
442:
443: BytesPerRowOfImage = BytesPerImageRow(dpy, image, req_width, req_xoffset);
444:
445: if ((BytesPerRowOfImage * req_height) <= BytesInRequestAvailableForImage)
446: {
447: PutImageRequest(dpy, d, gc, image, req_xoffset, req_yoffset, x, y,
448: req_width, req_height);
449: }
450: else
451: {
452: if (req_height > 1)
453: {
454: int SubImageHeight = BytesInRequestAvailableForImage /
455: BytesPerRowOfImage;
456:
457: if (SubImageHeight < 1) SubImageHeight = 1;
458:
459: PutSubImage(dpy, d, gc, image, req_xoffset, req_yoffset, x, y,
460: req_width, SubImageHeight);
461:
462: PutSubImage(dpy, d, gc, image, req_xoffset,
463: req_yoffset + SubImageHeight, x, y + SubImageHeight, req_width,
464: req_height - SubImageHeight);
465: }
466: else
467: {
468: int SubImageWidth = ((BytesInRequestAvailableForImage << 3) /
469: dpy->bitmap_pad) * dpy->bitmap_pad - left_pad;
470:
471: PutSubImage(dpy, d, gc, image, req_xoffset, req_yoffset, x, y,
472: SubImageWidth, req_height);
473:
474: PutSubImage(dpy, d, gc, image, req_xoffset + SubImageWidth,
475: req_yoffset, x + SubImageWidth, y, req_width - SubImageWidth,
476: req_height);
477: }
478: }
479: return;
480: }
481:
482: XPutImage (dpy, d, gc, image, req_xoffset,req_yoffset, x, y, req_width,
483: req_height)
484: register Display *dpy;
485: Drawable d;
486: GC gc;
487: register XImage *image;
488: int x, y;
489: unsigned int req_width, req_height;
490: int req_xoffset, req_yoffset;
491:
492: {
493: /* Does the display need to be locked and the GC flushed here? */
494: LockDisplay(dpy);
495: if ((req_width == 0) || (req_height == 0)) return;
496:
497: PutSubImage(dpy, d, gc, image, req_xoffset, req_yoffset, x, y, req_width,
498: req_height);
499:
500: /* Does the display need to be unlocked here? Are any status values
501: returned? */
502: UnlockDisplay(dpy);
503: return;
504: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.