|
|
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.