Home | History | Annotate | Line # | Download | only in src
      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