1 /* 2 3 Copyright 1986, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included in 12 all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21 Except as contained in this notice, the name of The Open Group shall not be 22 used in advertising or otherwise to promote the sale, use or other dealings 23 in 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 "Xutil.h" 32 #include <stdio.h> 33 #include <limits.h> 34 #include "Cr.h" 35 #include "ImUtil.h" 36 #include "reallocarray.h" 37 38 #if defined(__STDC__) && ((defined(sun) && defined(SVR4)) || defined(WIN32)) 39 #define RConst /**/ 40 #else 41 #define RConst const 42 #endif 43 44 /* assumes pad is a power of 2 */ 45 #define ROUNDUP(nbytes, pad) (((nbytes) + ((pad) - 1)) & ~(long)((pad) - 1)) 46 47 static unsigned char const _reverse_byte[0x100] = { 48 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 49 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 50 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 51 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 52 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 53 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 54 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 55 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 56 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 57 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 58 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 59 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 60 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 61 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 62 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 63 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 64 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 65 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 66 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 67 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 68 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 69 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 70 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 71 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 72 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 73 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 74 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 75 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 76 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 77 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 78 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 79 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff 80 }; 81 82 static unsigned char const _reverse_nibs[0x100] = { 83 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 84 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 85 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 86 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1, 0xf1, 87 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 88 0x82, 0x92, 0xa2, 0xb2, 0xc2, 0xd2, 0xe2, 0xf2, 89 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 90 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0xd3, 0xe3, 0xf3, 91 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 92 0x84, 0x94, 0xa4, 0xb4, 0xc4, 0xd4, 0xe4, 0xf4, 93 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 94 0x85, 0x95, 0xa5, 0xb5, 0xc5, 0xd5, 0xe5, 0xf5, 95 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, 96 0x86, 0x96, 0xa6, 0xb6, 0xc6, 0xd6, 0xe6, 0xf6, 97 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, 98 0x87, 0x97, 0xa7, 0xb7, 0xc7, 0xd7, 0xe7, 0xf7, 99 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, 100 0x88, 0x98, 0xa8, 0xb8, 0xc8, 0xd8, 0xe8, 0xf8, 101 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, 102 0x89, 0x99, 0xa9, 0xb9, 0xc9, 0xd9, 0xe9, 0xf9, 103 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a, 104 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa, 105 0x0b, 0x1b, 0x2b, 0x3b, 0x4b, 0x5b, 0x6b, 0x7b, 106 0x8b, 0x9b, 0xab, 0xbb, 0xcb, 0xdb, 0xeb, 0xfb, 107 0x0c, 0x1c, 0x2c, 0x3c, 0x4c, 0x5c, 0x6c, 0x7c, 108 0x8c, 0x9c, 0xac, 0xbc, 0xcc, 0xdc, 0xec, 0xfc, 109 0x0d, 0x1d, 0x2d, 0x3d, 0x4d, 0x5d, 0x6d, 0x7d, 110 0x8d, 0x9d, 0xad, 0xbd, 0xcd, 0xdd, 0xed, 0xfd, 111 0x0e, 0x1e, 0x2e, 0x3e, 0x4e, 0x5e, 0x6e, 0x7e, 112 0x8e, 0x9e, 0xae, 0xbe, 0xce, 0xde, 0xee, 0xfe, 113 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, 114 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff 115 }; 116 117 int 118 _XReverse_Bytes( 119 unsigned char *bpt, 120 int nb) 121 { 122 do { 123 *bpt = _reverse_byte[*bpt]; 124 bpt++; 125 } while (--nb > 0); 126 return 0; 127 } 128 129 130 /* XXX the following functions are declared int instead of void because various 131 * compilers and lints complain about later initialization of SwapFunc and/or 132 * (swapfunc == NoSwap) when void is used. 133 */ 134 135 /*ARGSUSED*/ 136 static void 137 NoSwap ( 138 register unsigned char *src, 139 register unsigned char *dest, 140 long srclen, 141 long srcinc, 142 long destinc, 143 unsigned int height, 144 int half_order) 145 { 146 long h = height; 147 148 if (srcinc == destinc) 149 memcpy((char *)dest, (char *)src, (int)(srcinc * (h - 1) + srclen)); 150 else 151 for (; --h >= 0; src += srcinc, dest += destinc) 152 memcpy((char *)dest, (char *)src, (int)srclen); 153 } 154 155 static void 156 SwapTwoBytes ( 157 register unsigned char *src, 158 register unsigned char *dest, 159 long srclen, long srcinc, long destinc, 160 unsigned int height, 161 int half_order) 162 { 163 long length = ROUNDUP(srclen, 2); 164 register long h, n; 165 166 srcinc -= length; 167 destinc -= length; 168 for (h = height; --h >= 0; src += srcinc, dest += destinc) { 169 if ((h == 0) && (srclen != length)) { 170 length -= 2; 171 if (half_order == MSBFirst) 172 *(dest + length) = *(src + length + 1); 173 else 174 *(dest + length + 1) = *(src + length); 175 } 176 for (n = length; n > 0; n -= 2, src += 2) { 177 *dest++ = *(src + 1); 178 *dest++ = *src; 179 } 180 } 181 } 182 183 static void 184 SwapThreeBytes ( 185 register unsigned char *src, 186 register unsigned char *dest, 187 long srclen, long srcinc, long destinc, 188 unsigned int height, 189 int byte_order) 190 { 191 long length = ((srclen + 2) / 3) * 3; 192 register long h, n; 193 194 srcinc -= length; 195 destinc -= length; 196 for (h = height; --h >= 0; src += srcinc, dest += destinc) { 197 if ((h == 0) && (srclen != length)) { 198 length -= 3; 199 if ((srclen - length) == 2) 200 *(dest + length + 1) = *(src + length + 1); 201 if (byte_order == MSBFirst) 202 *(dest + length) = *(src + length + 2); 203 else 204 *(dest + length + 2) = *(src + length); 205 } 206 for (n = length; n > 0; n -= 3, src += 3) { 207 *dest++ = *(src + 2); 208 *dest++ = *(src + 1); 209 *dest++ = *src; 210 } 211 } 212 } 213 214 static void 215 SwapFourBytes ( 216 register unsigned char *src, 217 register unsigned char *dest, 218 long srclen, long srcinc, long destinc, 219 unsigned int height, 220 int half_order) 221 { 222 long length = ROUNDUP(srclen, 4); 223 register long h, n; 224 225 srcinc -= length; 226 destinc -= length; 227 for (h = height; --h >= 0; src += srcinc, dest += destinc) { 228 if ((h == 0) && (srclen != length)) { 229 length -= 4; 230 if (half_order == MSBFirst) 231 *(dest + length) = *(src + length + 3); 232 if (((half_order == LSBFirst) && ((srclen - length) == 3)) || 233 ((half_order == MSBFirst) && (srclen & 2))) 234 *(dest + length + 1) = *(src + length + 2); 235 if (((half_order == MSBFirst) && ((srclen - length) == 3)) || 236 ((half_order == LSBFirst) && (srclen & 2))) 237 *(dest + length + 2) = *(src + length + 1); 238 if (half_order == LSBFirst) 239 *(dest + length + 3) = *(src + length); 240 } 241 for (n = length; n > 0; n -= 4, src += 4) { 242 *dest++ = *(src + 3); 243 *dest++ = *(src + 2); 244 *dest++ = *(src + 1); 245 *dest++ = *src; 246 } 247 } 248 } 249 250 static void 251 SwapWords ( 252 register unsigned char *src, 253 register unsigned char *dest, 254 long srclen, long srcinc, long destinc, 255 unsigned int height, 256 int half_order) 257 { 258 long length = ROUNDUP(srclen, 4); 259 register long h, n; 260 261 srcinc -= length; 262 destinc -= length; 263 for (h = height; --h >= 0; src += srcinc, dest += destinc) { 264 if ((h == 0) && (srclen != length)) { 265 length -= 4; 266 if (half_order == MSBFirst) 267 *(dest + length + 1) = *(src + length + 3); 268 if (((half_order == LSBFirst) && ((srclen - length) == 3)) || 269 ((half_order == MSBFirst) && (srclen & 2))) 270 *(dest + length) = *(src + length + 2); 271 if (((half_order == MSBFirst) && ((srclen - length) == 3)) || 272 ((half_order == LSBFirst) && (srclen & 2))) 273 *(dest + length + 3) = *(src + length + 1); 274 if (half_order == LSBFirst) 275 *(dest + length + 2) = *(src + length); 276 } 277 for (n = length; n > 0; n -= 4, src += 2) { 278 *dest++ = *(src + 2); 279 *dest++ = *(src + 3); 280 *dest++ = *src++; 281 *dest++ = *src++; 282 } 283 } 284 } 285 286 static void 287 SwapNibbles( 288 register unsigned char *src, 289 register unsigned char *dest, 290 long srclen, long srcinc, long destinc, 291 unsigned int height) 292 { 293 register long h, n; 294 register const unsigned char *rev = _reverse_nibs; 295 296 srcinc -= srclen; 297 destinc -= srclen; 298 for (h = height; --h >= 0; src += srcinc, dest += destinc) 299 for (n = srclen; --n >= 0; ) 300 *dest++ = rev[*src++]; 301 } 302 303 static void 304 ShiftNibblesLeft ( 305 register unsigned char *src, 306 register unsigned char *dest, 307 long srclen, long srcinc, long destinc, 308 unsigned int height, 309 int nibble_order) 310 { 311 register long h, n; 312 register unsigned char c1, c2; 313 314 srcinc -= srclen; 315 destinc -= srclen; 316 if (nibble_order == MSBFirst) { 317 for (h = height; --h >= 0; src += srcinc, dest += destinc) 318 for (n = srclen; --n >= 0; ) { 319 c1 = *src++; 320 c2 = *src; 321 *dest++ = ((c1 & 0x0f) << 4) | ((c2 & (unsigned)0xf0) >> 4); 322 } 323 } else { 324 for (h = height; --h >= 0; src += srcinc, dest += destinc) 325 for (n = srclen; --n >= 0; ) { 326 c1 = *src++; 327 c2 = *src; 328 *dest++ = ((c2 & 0x0f) << 4) | ((c1 & (unsigned)0xf0) >> 4); 329 } 330 } 331 } 332 333 /*ARGSUSED*/ 334 static void 335 SwapBits( 336 register unsigned char *src, 337 register unsigned char *dest, 338 long srclen, long srcinc, long destinc, 339 unsigned int height, 340 int half_order) 341 { 342 register long h, n; 343 register const unsigned char *rev = _reverse_byte; 344 345 srcinc -= srclen; 346 destinc -= srclen; 347 for (h = height; --h >= 0; src += srcinc, dest += destinc) 348 for (n = srclen; --n >= 0; ) 349 *dest++ = rev[*src++]; 350 } 351 352 static void 353 SwapBitsAndTwoBytes( 354 register unsigned char *src, 355 register unsigned char *dest, 356 long srclen, long srcinc, long destinc, 357 unsigned int height, 358 int half_order) 359 { 360 long length = ROUNDUP(srclen, 2); 361 register long h, n; 362 register const unsigned char *rev = _reverse_byte; 363 364 srcinc -= length; 365 destinc -= length; 366 for (h = height; --h >= 0; src += srcinc, dest += destinc) { 367 if ((h == 0) && (srclen != length)) { 368 length -= 2; 369 if (half_order == MSBFirst) 370 *(dest + length) = rev[*(src + length + 1)]; 371 else 372 *(dest + length + 1) = rev[*(src + length)]; 373 } 374 for (n = length; n > 0; n -= 2, src += 2) { 375 *dest++ = rev[*(src + 1)]; 376 *dest++ = rev[*src]; 377 } 378 } 379 } 380 381 static void 382 SwapBitsAndFourBytes( 383 register unsigned char *src, 384 register unsigned char *dest, 385 long srclen, long srcinc, long destinc, 386 unsigned int height, 387 int half_order) 388 { 389 long length = ROUNDUP(srclen, 4); 390 register long h, n; 391 register const unsigned char *rev = _reverse_byte; 392 393 srcinc -= length; 394 destinc -= length; 395 for (h = height; --h >= 0; src += srcinc, dest += destinc) { 396 if ((h == 0) && (srclen != length)) { 397 length -= 4; 398 if (half_order == MSBFirst) 399 *(dest + length) = rev[*(src + length + 3)]; 400 if (((half_order == LSBFirst) && ((srclen - length) == 3)) || 401 ((half_order == MSBFirst) && (srclen & 2))) 402 *(dest + length + 1) = rev[*(src + length + 2)]; 403 if (((half_order == MSBFirst) && ((srclen - length) == 3)) || 404 ((half_order == LSBFirst) && (srclen & 2))) 405 *(dest + length + 2) = rev[*(src + length + 1)]; 406 if (half_order == LSBFirst) 407 *(dest + length + 3) = rev[*(src + length)]; 408 } 409 for (n = length; n > 0; n -= 4, src += 4) { 410 *dest++ = rev[*(src + 3)]; 411 *dest++ = rev[*(src + 2)]; 412 *dest++ = rev[*(src + 1)]; 413 *dest++ = rev[*src]; 414 } 415 } 416 } 417 418 static void 419 SwapBitsAndWords( 420 register unsigned char *src, 421 register unsigned char *dest, 422 long srclen, long srcinc, long destinc, 423 unsigned int height, 424 int half_order) 425 { 426 long length = ROUNDUP(srclen, 4); 427 register long h, n; 428 register const unsigned char *rev = _reverse_byte; 429 430 srcinc -= length; 431 destinc -= length; 432 for (h = height; --h >= 0; src += srcinc, dest += destinc) { 433 if ((h == 0) && (srclen != length)) { 434 length -= 4; 435 if (half_order == MSBFirst) 436 *(dest + length + 1) = rev[*(src + length + 3)]; 437 if (((half_order == LSBFirst) && ((srclen - length) == 3)) || 438 ((half_order == MSBFirst) && (srclen & 2))) 439 *(dest + length) = rev[*(src + length + 2)]; 440 if (((half_order == MSBFirst) && ((srclen - length) == 3)) || 441 ((half_order == LSBFirst) && (srclen & 2))) 442 *(dest + length + 3) = rev[*(src + length + 1)]; 443 if (half_order == LSBFirst) 444 *(dest + length + 2) = rev[*(src + length)]; 445 } 446 for (n = length; n > 0; n -= 4, src += 2) { 447 *dest++ = rev[*(src + 2)]; 448 *dest++ = rev[*(src + 3)]; 449 *dest++ = rev[*src++]; 450 *dest++ = rev[*src++]; 451 } 452 } 453 } 454 455 /* 456 457 The following table gives the bit ordering within bytes (when accessed 458 sequentially) for a scanline containing 32 bits, with bits numbered 0 to 459 31, where bit 0 should be leftmost on the display. For a given byte 460 labelled A-B, A is for the most significant bit of the byte, and B is 461 for the least significant bit. 462 463 legend: 464 1 scanline-unit = 8 465 2 scanline-unit = 16 466 4 scanline-unit = 32 467 M byte-order = MostSignificant 468 L byte-order = LeastSignificant 469 m bit-order = MostSignificant 470 l bit-order = LeastSignificant 471 472 473 format ordering 474 475 1Mm 00-07 08-15 16-23 24-31 476 2Mm 00-07 08-15 16-23 24-31 477 4Mm 00-07 08-15 16-23 24-31 478 1Ml 07-00 15-08 23-16 31-24 479 2Ml 15-08 07-00 31-24 23-16 480 4Ml 31-24 23-16 15-08 07-00 481 1Lm 00-07 08-15 16-23 24-31 482 2Lm 08-15 00-07 24-31 16-23 483 4Lm 24-31 16-23 08-15 00-07 484 1Ll 07-00 15-08 23-16 31-24 485 2Ll 07-00 15-08 23-16 31-24 486 4Ll 07-00 15-08 23-16 31-24 487 488 489 The following table gives the required conversion between any two 490 formats. It is based strictly on the table above. If you believe one, 491 you should believe the other. 492 493 legend: 494 n no changes 495 s reverse 8-bit units within 16-bit units 496 l reverse 8-bit units within 32-bit units 497 w reverse 16-bit units within 32-bit units 498 R reverse bits within 8-bit units 499 S s+R 500 L l+R 501 W w+R 502 503 */ 504 505 static void (* RConst (SwapFunction[12][12]))( 506 register unsigned char *src, 507 register unsigned char *dest, 508 long srclen, 509 long srcinc, 510 long destinc, 511 unsigned int height, 512 int half_order) = { 513 #define n NoSwap, 514 #define s SwapTwoBytes, 515 #define l SwapFourBytes, 516 #define w SwapWords, 517 #define R SwapBits, 518 #define S SwapBitsAndTwoBytes, 519 #define L SwapBitsAndFourBytes, 520 #define W SwapBitsAndWords, 521 522 /* 1Mm 2Mm 4Mm 1Ml 2Ml 4Ml 1Lm 2Lm 4Lm 1Ll 2Ll 4Ll */ 523 /* 1Mm */ { n n n R S L n s l R R R }, 524 /* 2Mm */ { n n n R S L n s l R R R }, 525 /* 4Mm */ { n n n R S L n s l R R R }, 526 /* 1Ml */ { R R R n s l R S L n n n }, 527 /* 2Ml */ { S S S s n w S R W s s s }, 528 /* 4Ml */ { L L L l w n L W R l l l }, 529 /* 1Lm */ { n n n R S L n s l R R R }, 530 /* 2Lm */ { s s s S R W s n w S S S }, 531 /* 4Lm */ { l l l L W R l w n L L L }, 532 /* 1Ll */ { R R R n s l R S L n n n }, 533 /* 2Ll */ { R R R n s l R S L n n n }, 534 /* 4Ll */ { R R R n s l R S L n n n } 535 536 #undef n 537 #undef s 538 #undef l 539 #undef w 540 #undef R 541 #undef S 542 #undef L 543 #undef W 544 545 }; 546 547 /* Of course, the table above is a lie. We also need to factor in the 548 * order of the source data to cope with swapping half of a unit at the 549 * end of a scanline, since we are trying to avoid de-ref'ing off the 550 * end of the source. 551 * 552 * Defines whether the first half of a unit has the first half of the data 553 */ 554 static int const HalfOrder[12] = { 555 LSBFirst, /* 1Mm */ 556 LSBFirst, /* 2Mm */ 557 LSBFirst, /* 4Mm */ 558 LSBFirst, /* 1Ml */ 559 MSBFirst, /* 2Ml */ 560 MSBFirst, /* 4Ml */ 561 LSBFirst, /* 1Lm */ 562 MSBFirst, /* 2Lm */ 563 MSBFirst, /* 4Lm */ 564 LSBFirst, /* 1Ll */ 565 LSBFirst, /* 2Ll */ 566 LSBFirst /* 4Ll */ 567 }; 568 569 /* Finally, for SwapWords cases, the half order depends not just on the source 570 * but also on the destination scanline unit. Use of this table changes some 571 * MSBFirsts to LSBFirsts that are "do not care" (because the function will be 572 * NoSwap or SwapBits) in addition to changing the desired ones. 573 */ 574 575 static int const HalfOrderWord[12] = { 576 MSBFirst, /* 1Mm */ 577 MSBFirst, /* 2Mm */ 578 MSBFirst, /* 4Mm */ 579 MSBFirst, /* 1Ml */ 580 MSBFirst, /* 2Ml */ 581 LSBFirst, /* 4Ml */ 582 MSBFirst, /* 1Lm */ 583 MSBFirst, /* 2Lm */ 584 LSBFirst, /* 4Lm */ 585 MSBFirst, /* 1Ll */ 586 MSBFirst, /* 2Ll */ 587 MSBFirst /* 4Ll */ 588 }; 589 590 /* 591 * This macro creates a value from 0 to 11 suitable for indexing 592 * into the table above. 593 */ 594 #define ComposeIndex(bitmap_unit, bitmap_bit_order, byte_order) \ 595 (((bitmap_unit == 32) ? 2 : ((bitmap_unit == 16) ? 1 : 0)) \ 596 + (((bitmap_bit_order == MSBFirst) ? 0 : 3) \ 597 + ((byte_order == MSBFirst) ? 0 : 6))) 598 599 /* Cancel a GetReq operation, before doing _XSend or Data */ 600 601 #define UnGetReq(name)\ 602 dpy->bufptr -= SIZEOF(x##name##Req);\ 603 X_DPY_REQUEST_DECREMENT(dpy) 604 605 static void 606 SendXYImage( 607 register Display *dpy, 608 register xPutImageReq *req, 609 register XImage *image, 610 int req_xoffset, int req_yoffset) 611 { 612 register int j; 613 long total_xoffset, bytes_per_src, bytes_per_dest, length; 614 long bytes_per_line, bytes_per_src_plane, bytes_per_dest_plane; 615 char *src, *dest, *buf; 616 char *extra = (char *)NULL; 617 register void (*swapfunc)( 618 register unsigned char *src, 619 register unsigned char *dest, 620 long srclen, 621 long srcinc, 622 long destinc, 623 unsigned int height, 624 int half_order); 625 int half_order; 626 627 total_xoffset = image->xoffset + req_xoffset; 628 req->leftPad = total_xoffset & (dpy->bitmap_unit - 1); 629 total_xoffset = (unsigned)(total_xoffset - req->leftPad) >> 3; 630 /* The protocol requires left-pad of zero on all ZPixmap, even 631 * though the 1-bit case is identical to bitmap format. This is a 632 * bug in the protocol, caused because 1-bit ZPixmap was added late 633 * in the game. Hairy shifting code compensation isn't worth it, 634 * just use XYPixmap format instead. 635 */ 636 if ((req->leftPad != 0) && (req->format == ZPixmap)) 637 req->format = XYPixmap; 638 bytes_per_dest = (unsigned long)ROUNDUP((long)req->width + req->leftPad, 639 dpy->bitmap_pad) >> 3; 640 bytes_per_dest_plane = bytes_per_dest * req->height; 641 length = bytes_per_dest_plane * image->depth; 642 req->length += (length + 3) >> 2; 643 644 swapfunc = SwapFunction[ComposeIndex(image->bitmap_unit, 645 image->bitmap_bit_order, 646 image->byte_order)] 647 [ComposeIndex(dpy->bitmap_unit, 648 dpy->bitmap_bit_order, 649 dpy->byte_order)]; 650 half_order = HalfOrder[ComposeIndex(image->bitmap_unit, 651 image->bitmap_bit_order, 652 image->byte_order)]; 653 if (half_order == MSBFirst) 654 half_order = HalfOrderWord[ComposeIndex(dpy->bitmap_unit, 655 dpy->bitmap_bit_order, 656 dpy->byte_order)]; 657 658 src = image->data + (image->bytes_per_line * req_yoffset) + total_xoffset; 659 660 /* when total_xoffset > 0, we have to worry about stepping off the 661 * end of image->data. 662 */ 663 if ((swapfunc == NoSwap) && 664 (image->bytes_per_line == bytes_per_dest) && 665 (((total_xoffset == 0) && 666 ((image->depth == 1) || (image->height == req->height))) || 667 ((image->depth == 1) && 668 ((req_yoffset + req->height) < (unsigned)image->height)))) { 669 Data(dpy, src, length); 670 return; 671 } 672 673 length = ROUNDUP(length, 4); 674 if ((dpy->bufptr + length) > dpy->bufmax) { 675 if ((buf = _XAllocScratch(dpy, length)) == NULL) { 676 UnGetReq(PutImage); 677 return; 678 } 679 } 680 else 681 buf = dpy->bufptr; 682 683 bytes_per_src = (req->width + req->leftPad + (unsigned)7) >> 3; 684 bytes_per_line = image->bytes_per_line; 685 bytes_per_src_plane = bytes_per_line * image->height; 686 total_xoffset &= (image->bitmap_unit - 1) >> 3; 687 688 if ((total_xoffset > 0) && 689 (image->byte_order != image->bitmap_bit_order)) { 690 char *temp; 691 long bytes_per_temp_plane, temp_length; 692 693 bytes_per_line = bytes_per_src + total_xoffset; 694 src -= total_xoffset; 695 bytes_per_temp_plane = bytes_per_line * req->height; 696 temp_length = ROUNDUP(bytes_per_temp_plane * image->depth, 4); 697 if (buf == dpy->bufptr) { 698 if (! (temp = _XAllocScratch(dpy, temp_length))) { 699 UnGetReq(PutImage); 700 return; 701 } 702 } 703 else 704 if ((extra = temp = Xmalloc(temp_length)) == NULL) { 705 UnGetReq(PutImage); 706 return; 707 } 708 709 swapfunc = SwapFunction[ComposeIndex(image->bitmap_unit, 710 image->bitmap_bit_order, 711 image->byte_order)] 712 [ComposeIndex(image->bitmap_unit, 713 dpy->byte_order, 714 dpy->byte_order)]; 715 for (dest = temp, j = image->depth; 716 --j >= 0; 717 src += bytes_per_src_plane, dest += bytes_per_temp_plane) 718 (*swapfunc)((unsigned char *)src, (unsigned char *)dest, 719 bytes_per_line, (long)image->bytes_per_line, 720 bytes_per_line, req->height, half_order); 721 swapfunc = SwapFunction[ComposeIndex(image->bitmap_unit, 722 dpy->byte_order, 723 dpy->byte_order)] 724 [ComposeIndex(dpy->bitmap_unit, 725 dpy->bitmap_bit_order, 726 dpy->byte_order)]; 727 half_order = HalfOrder[ComposeIndex(image->bitmap_unit, 728 dpy->byte_order, 729 dpy->byte_order)]; 730 src = temp + total_xoffset; 731 bytes_per_src_plane = bytes_per_temp_plane; 732 } 733 734 for (dest = buf, j = image->depth; 735 --j >= 0; 736 src += bytes_per_src_plane, dest += bytes_per_dest_plane) 737 (*swapfunc)((unsigned char *)src, (unsigned char *)dest, 738 bytes_per_src, bytes_per_line, 739 bytes_per_dest, req->height, half_order); 740 741 Xfree(extra); 742 743 if (buf == dpy->bufptr) 744 dpy->bufptr += length; 745 else 746 _XSend(dpy, buf, length); 747 } 748 749 static void 750 SendZImage( 751 register Display *dpy, 752 register xPutImageReq *req, 753 register XImage *image, 754 int req_xoffset, int req_yoffset, 755 int dest_bits_per_pixel, int dest_scanline_pad) 756 { 757 long bytes_per_src, bytes_per_dest, length; 758 unsigned char *src, *dest; 759 unsigned char *shifted_src = NULL; 760 761 req->leftPad = 0; 762 bytes_per_src = ROUNDUP((long)req->width * image->bits_per_pixel, 8) >> 3; 763 bytes_per_dest = ROUNDUP((long)req->width * dest_bits_per_pixel, 764 dest_scanline_pad) >> 3; 765 length = bytes_per_dest * req->height; 766 req->length += (length + 3) >> 2; 767 768 src = (unsigned char *)image->data + 769 (req_yoffset * image->bytes_per_line) + 770 ((req_xoffset * image->bits_per_pixel) >> 3); 771 if ((image->bits_per_pixel == 4) && ((unsigned int) req_xoffset & 0x01)) { 772 if (! (shifted_src = Xmallocarray(req->height, image->bytes_per_line))) { 773 UnGetReq(PutImage); 774 return; 775 } 776 777 ShiftNibblesLeft(src, shifted_src, bytes_per_src, 778 (long) image->bytes_per_line, 779 (long) image->bytes_per_line, req->height, 780 image->byte_order); 781 src = shifted_src; 782 } 783 784 /* when req_xoffset > 0, we have to worry about stepping off the 785 * end of image->data. 786 */ 787 if (((image->byte_order == dpy->byte_order) || 788 (image->bits_per_pixel == 8)) && 789 ((long)image->bytes_per_line == bytes_per_dest) && 790 ((req_xoffset == 0) || 791 ((req_yoffset + req->height) < (unsigned)image->height))) { 792 Data(dpy, (char *)src, length); 793 Xfree(shifted_src); 794 return; 795 } 796 797 length = ROUNDUP(length, 4); 798 if ((dpy->bufptr + length) <= dpy->bufmax) 799 dest = (unsigned char *)dpy->bufptr; 800 else 801 if ((dest = (unsigned char *) 802 _XAllocScratch(dpy, length)) == NULL) { 803 Xfree(shifted_src); 804 UnGetReq(PutImage); 805 return; 806 } 807 808 if ((image->byte_order == dpy->byte_order) || 809 (image->bits_per_pixel == 8)) 810 NoSwap(src, dest, bytes_per_src, (long)image->bytes_per_line, 811 bytes_per_dest, req->height, image->byte_order); 812 else if (image->bits_per_pixel == 32) 813 SwapFourBytes(src, dest, bytes_per_src, (long)image->bytes_per_line, 814 bytes_per_dest, req->height, image->byte_order); 815 else if (image->bits_per_pixel == 24) 816 SwapThreeBytes(src, dest, bytes_per_src, (long)image->bytes_per_line, 817 bytes_per_dest, req->height, image->byte_order); 818 else if (image->bits_per_pixel == 16) 819 SwapTwoBytes(src, dest, bytes_per_src, (long)image->bytes_per_line, 820 bytes_per_dest, req->height, image->byte_order); 821 else 822 SwapNibbles(src, dest, bytes_per_src, (long)image->bytes_per_line, 823 bytes_per_dest, req->height); 824 825 if (dest == (unsigned char *)dpy->bufptr) 826 dpy->bufptr += length; 827 else 828 _XSend(dpy, (char *)dest, length); 829 830 Xfree(shifted_src); 831 } 832 833 static void 834 PutImageRequest( 835 register Display *dpy, 836 Drawable d, 837 GC gc, 838 register XImage *image, 839 int req_xoffset, int req_yoffset, 840 int x, int y, 841 unsigned int req_width, unsigned int req_height, 842 int dest_bits_per_pixel, int dest_scanline_pad) 843 { 844 register xPutImageReq *req; 845 846 GetReq(PutImage, req); 847 req->drawable = d; 848 req->gc = gc->gid; 849 req->dstX = x; 850 req->dstY = y; 851 req->width = req_width; 852 req->height = req_height; 853 req->depth = image->depth; 854 req->format = image->format; 855 if ((image->bits_per_pixel == 1) || (image->format != ZPixmap)) 856 SendXYImage(dpy, req, image, req_xoffset, req_yoffset); 857 else 858 SendZImage(dpy, req, image, req_xoffset, req_yoffset, 859 dest_bits_per_pixel, dest_scanline_pad); 860 } 861 862 static void 863 PutSubImage ( 864 register Display *dpy, 865 Drawable d, 866 GC gc, 867 register XImage *image, 868 int req_xoffset, 869 int req_yoffset, 870 int x, int y, 871 unsigned int req_width, 872 unsigned int req_height, 873 int dest_bits_per_pixel, 874 int dest_scanline_pad) 875 { 876 int left_pad, BytesPerRow, Available; 877 878 if ((req_width == 0) || (req_height == 0)) 879 return; 880 881 Available = ((65536 < dpy->max_request_size) ? (65536 << 2) 882 : (dpy->max_request_size << 2)) 883 - SIZEOF(xPutImageReq); 884 885 if ((image->bits_per_pixel == 1) || (image->format != ZPixmap)) { 886 left_pad = (image->xoffset + req_xoffset) & (dpy->bitmap_unit - 1); 887 BytesPerRow = (ROUNDUP((long)req_width + left_pad, 888 dpy->bitmap_pad) >> 3) * image->depth; 889 } else { 890 left_pad = 0; 891 BytesPerRow = ROUNDUP((long)req_width * dest_bits_per_pixel, 892 dest_scanline_pad) >> 3; 893 } 894 895 if ((BytesPerRow * req_height) <= Available) { 896 PutImageRequest(dpy, d, gc, image, req_xoffset, req_yoffset, x, y, 897 req_width, req_height, 898 dest_bits_per_pixel, dest_scanline_pad); 899 } else if (req_height > 1) { 900 int SubImageHeight = Available / BytesPerRow; 901 902 if (SubImageHeight == 0) 903 SubImageHeight = 1; 904 905 PutSubImage(dpy, d, gc, image, req_xoffset, req_yoffset, x, y, 906 req_width, (unsigned int) SubImageHeight, 907 dest_bits_per_pixel, dest_scanline_pad); 908 909 PutSubImage(dpy, d, gc, image, req_xoffset, 910 req_yoffset + SubImageHeight, x, y + SubImageHeight, 911 req_width, req_height - SubImageHeight, 912 dest_bits_per_pixel, dest_scanline_pad); 913 } else { 914 int SubImageWidth = ((((Available << 3) / dest_scanline_pad) 915 * dest_scanline_pad) - left_pad) 916 / dest_bits_per_pixel; 917 918 PutSubImage(dpy, d, gc, image, req_xoffset, req_yoffset, x, y, 919 (unsigned int) SubImageWidth, 1, 920 dest_bits_per_pixel, dest_scanline_pad); 921 922 PutSubImage(dpy, d, gc, image, req_xoffset + SubImageWidth, 923 req_yoffset, x + SubImageWidth, y, 924 req_width - SubImageWidth, 1, 925 dest_bits_per_pixel, dest_scanline_pad); 926 } 927 } 928 929 930 int 931 XPutImage ( 932 register Display *dpy, 933 Drawable d, 934 GC gc, 935 register XImage *image, 936 int req_xoffset, 937 int req_yoffset, 938 int x, 939 int y, 940 unsigned int req_width, 941 unsigned int req_height) 942 943 { 944 long width = req_width; 945 long height = req_height; 946 int dest_bits_per_pixel, dest_scanline_pad; 947 948 if (req_xoffset < 0) { 949 width += req_xoffset; 950 req_xoffset = 0; 951 } 952 if (req_yoffset < 0) { 953 height += req_yoffset; 954 req_yoffset = 0; 955 } 956 if ((req_xoffset + width) > image->width) 957 width = image->width - req_xoffset; 958 if ((req_yoffset + height) > image->height) 959 height = image->height - req_yoffset; 960 if ((width <= 0) || (height <= 0)) 961 return 0; 962 if (width > USHRT_MAX) 963 width = USHRT_MAX; 964 if (height > USHRT_MAX) 965 height = USHRT_MAX; 966 967 if ((image->bits_per_pixel == 1) || (image->format != ZPixmap)) { 968 dest_bits_per_pixel = 1; 969 dest_scanline_pad = dpy->bitmap_pad; 970 } else { 971 register int n; 972 register ScreenFormat *format; 973 974 dest_bits_per_pixel = image->bits_per_pixel; 975 dest_scanline_pad = image->bitmap_pad; 976 for (n = dpy->nformats, format = dpy->pixmap_format; --n >= 0; format++) 977 if (format->depth == image->depth) { 978 dest_bits_per_pixel = format->bits_per_pixel; 979 dest_scanline_pad = format->scanline_pad; 980 } 981 if (dest_bits_per_pixel != image->bits_per_pixel) { 982 XImage img; 983 register long i, j; 984 /* XXX slow, but works */ 985 img.width = width; 986 img.height = height; 987 img.xoffset = 0; 988 img.format = ZPixmap; 989 img.byte_order = dpy->byte_order; 990 img.bitmap_unit = dpy->bitmap_unit; 991 img.bitmap_bit_order = dpy->bitmap_bit_order; 992 img.bitmap_pad = dest_scanline_pad; 993 img.depth = image->depth; 994 img.bits_per_pixel = dest_bits_per_pixel; 995 img.bytes_per_line = ROUNDUP((dest_bits_per_pixel * width), 996 dest_scanline_pad) >> 3; 997 img.data = Xmallocarray(height, img.bytes_per_line); 998 if (img.data == NULL) 999 return 0; 1000 _XInitImageFuncPtrs(&img); 1001 for (j = height; --j >= 0; ) 1002 for (i = width; --i >= 0; ) 1003 XPutPixel(&img, i, j, XGetPixel(image, req_xoffset + i, 1004 req_yoffset + j)); 1005 LockDisplay(dpy); 1006 FlushGC(dpy, gc); 1007 PutSubImage(dpy, d, gc, &img, 0, 0, x, y, 1008 (unsigned int) width, (unsigned int) height, 1009 dest_bits_per_pixel, dest_scanline_pad); 1010 UnlockDisplay(dpy); 1011 SyncHandle(); 1012 Xfree(img.data); 1013 return 0; 1014 } 1015 } 1016 1017 LockDisplay(dpy); 1018 FlushGC(dpy, gc); 1019 1020 PutSubImage(dpy, d, gc, image, req_xoffset, req_yoffset, x, y, 1021 (unsigned int) width, (unsigned int) height, 1022 dest_bits_per_pixel, dest_scanline_pad); 1023 1024 UnlockDisplay(dpy); 1025 SyncHandle(); 1026 #ifdef USE_DYNAMIC_XCURSOR 1027 if (image->bits_per_pixel == 1 && 1028 x == 0 && y == 0 && 1029 width == image->width && height == image->height && 1030 gc->values.function == GXcopy && 1031 (gc->values.plane_mask & 1)) 1032 { 1033 _XNoticePutBitmap (dpy, d, image); 1034 } 1035 #endif 1036 return 0; 1037 } 1038