Ignore the LPSURFACE bit if ALLOCONLOAD is set.
[wine/multimedia.git] / graphics / x11drv / dib.c
blobfb7d33294c68679fa71e6246810e2b8c16e8a31b
1 /*
2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include "ts_xlib.h"
24 #ifdef HAVE_LIBXXSHM
25 #include <X11/extensions/XShm.h>
26 # ifdef HAVE_SYS_SHM_H
27 # include <sys/shm.h>
28 # endif
29 # ifdef HAVE_SYS_IPC_H
30 # include <sys/ipc.h>
31 # endif
32 #endif /* defined(HAVE_LIBXXSHM) */
34 #include <stdlib.h>
35 #include <string.h>
36 #include "windef.h"
37 #include "bitmap.h"
38 #include "x11drv.h"
39 #include "wine/debug.h"
40 #include "gdi.h"
41 #include "palette.h"
42 #include "global.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
45 WINE_DECLARE_DEBUG_CHANNEL(x11drv);
47 static int ximageDepthTable[32];
49 /* This structure holds the arguments for DIB_SetImageBits() */
50 typedef struct
52 X11DRV_PDEVICE *physDev;
53 LPCVOID bits;
54 XImage *image;
55 PALETTEENTRY *palentry;
56 int lines;
57 DWORD infoWidth;
58 WORD depth;
59 WORD infoBpp;
60 WORD compression;
61 RGBQUAD *colorMap;
62 int nColorMap;
63 Drawable drawable;
64 GC gc;
65 int xSrc;
66 int ySrc;
67 int xDest;
68 int yDest;
69 int width;
70 int height;
71 DWORD rMask;
72 DWORD gMask;
73 DWORD bMask;
74 BOOL useShm;
75 int dibpitch;
76 } X11DRV_DIB_IMAGEBITS_DESCR;
79 enum Rle_EscapeCodes
81 RLE_EOL = 0, /* End of line */
82 RLE_END = 1, /* End of bitmap */
83 RLE_DELTA = 2 /* Delta */
86 /***********************************************************************
87 * X11DRV_DIB_GetXImageWidthBytes
89 * Return the width of an X image in bytes
91 inline static int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
93 if (!depth || depth > 32) goto error;
95 if (!ximageDepthTable[depth-1])
97 XImage *testimage = XCreateImage( gdi_display, visual, depth,
98 ZPixmap, 0, NULL, 1, 1, 32, 20 );
99 if (testimage)
101 ximageDepthTable[depth-1] = testimage->bits_per_pixel;
102 XDestroyImage( testimage );
104 else ximageDepthTable[depth-1] = -1;
106 if (ximageDepthTable[depth-1] != -1)
107 return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
109 error:
110 WARN( "(%d): Unsupported depth\n", depth );
111 return 4 * width;
115 /***********************************************************************
116 * X11DRV_DIB_CreateXImage
118 * Create an X image.
120 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
122 int width_bytes;
123 XImage *image;
125 wine_tsx11_lock();
126 width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
127 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
128 calloc( height, width_bytes ),
129 width, height, 32, width_bytes );
130 wine_tsx11_unlock();
131 return image;
135 /***********************************************************************
136 * DIB_GetBitmapInfo
138 * Get the info from a bitmap header.
139 * Return 1 for INFOHEADER, 0 for COREHEADER, -1 for error.
141 static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, DWORD *width,
142 int *height, WORD *bpp, WORD *compr )
144 if (header->biSize == sizeof(BITMAPCOREHEADER))
146 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
147 *width = core->bcWidth;
148 *height = core->bcHeight;
149 *bpp = core->bcBitCount;
150 *compr = 0;
151 return 0;
153 if (header->biSize >= sizeof(BITMAPINFOHEADER))
155 *width = header->biWidth;
156 *height = header->biHeight;
157 *bpp = header->biBitCount;
158 *compr = header->biCompression;
159 return 1;
161 ERR("(%ld): unknown/wrong size for header\n", header->biSize );
162 return -1;
166 /***********************************************************************
167 * X11DRV_DIB_GenColorMap
169 * Fills the color map of a bitmap palette. Should not be called
170 * for a >8-bit deep bitmap.
172 int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
173 WORD coloruse, WORD depth, BOOL quads,
174 const void *colorPtr, int start, int end )
176 int i;
178 if (coloruse == DIB_RGB_COLORS)
180 int max = 1 << depth;
182 if (end > max) end = max;
184 if (quads)
186 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
188 if (depth == 1) /* Monochrome */
189 for (i = start; i < end; i++, rgb++)
190 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
191 rgb->rgbBlue > 255*3/2);
192 else
193 for (i = start; i < end; i++, rgb++)
194 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbRed,
195 rgb->rgbGreen,
196 rgb->rgbBlue));
198 else
200 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
202 if (depth == 1) /* Monochrome */
203 for (i = start; i < end; i++, rgb++)
204 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
205 rgb->rgbtBlue > 255*3/2);
206 else
207 for (i = start; i < end; i++, rgb++)
208 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbtRed,
209 rgb->rgbtGreen,
210 rgb->rgbtBlue));
213 else /* DIB_PAL_COLORS */
215 if (colorPtr) {
216 WORD * index = (WORD *)colorPtr;
218 for (i = start; i < end; i++, index++)
219 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
220 } else {
221 for (i = start; i < end; i++)
222 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(i) );
226 return colorMapping;
229 /***********************************************************************
230 * X11DRV_DIB_BuildColorMap
232 * Build the color map from the bitmap palette. Should not be called
233 * for a >8-bit deep bitmap.
235 int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
236 const BITMAPINFO *info, int *nColors )
238 int colors;
239 BOOL isInfo;
240 const void *colorPtr;
241 int *colorMapping;
243 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
245 colors = info->bmiHeader.biClrUsed;
246 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
247 colorPtr = info->bmiColors;
249 else /* assume BITMAPCOREINFO */
251 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
252 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
255 if (colors > 256)
257 ERR("called with >256 colors!\n");
258 return NULL;
261 /* just so CopyDIBSection doesn't have to create an identity palette */
262 if (coloruse == (WORD)-1) colorPtr = NULL;
264 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
265 colors * sizeof(int) )))
266 return NULL;
268 *nColors = colors;
269 return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
270 isInfo, colorPtr, 0, colors);
274 /***********************************************************************
275 * X11DRV_DIB_MapColor
277 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
279 int color;
281 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
282 return oldcol;
284 for (color = 0; color < nPhysMap; color++)
285 if (physMap[color] == phys)
286 return color;
288 WARN("Strange color %08x\n", phys);
289 return 0;
293 /*********************************************************************
294 * X11DRV_DIB_GetNearestIndex
296 * Helper for X11DRV_DIB_GetDIBits.
297 * Returns the nearest colour table index for a given RGB.
298 * Nearest is defined by minimizing the sum of the squares.
300 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
302 INT i, best = -1, diff, bestdiff = -1;
303 RGBQUAD *color;
305 for(color = colormap, i = 0; i < numColors; color++, i++) {
306 diff = (r - color->rgbRed) * (r - color->rgbRed) +
307 (g - color->rgbGreen) * (g - color->rgbGreen) +
308 (b - color->rgbBlue) * (b - color->rgbBlue);
309 if(diff == 0)
310 return i;
311 if(best == -1 || diff < bestdiff) {
312 best = i;
313 bestdiff = diff;
316 return best;
318 /*********************************************************************
319 * X11DRV_DIB_MaskToShift
321 * Helper for X11DRV_DIB_GetDIBits.
322 * Returns the by how many bits to shift a given color so that it is
323 * in the proper position.
325 static INT X11DRV_DIB_MaskToShift(DWORD mask)
327 int shift;
329 if (mask==0)
330 return 0;
332 shift=0;
333 while ((mask&1)==0) {
334 mask>>=1;
335 shift++;
337 return shift;
340 /***********************************************************************
341 * X11DRV_DIB_Convert_any_asis
343 * All X11DRV_DIB_Convert_Xxx functions take at least the following
344 * parameters:
345 * - width
346 * This is the width in pixel of the surface to copy. This may be less
347 * than the full width of the image.
348 * - height
349 * The number of lines to copy. This may be less than the full height
350 * of the image. This is always >0.
351 * - srcbits
352 * Points to the first byte containing data to be copied. If the source
353 * surface starts are coordinates (x,y) then this is:
354 * image_ptr+x*bytes_pre_pixel+y*bytes_per_line
355 * (with further adjustments for top-down/bottom-up images)
356 * - srclinebytes
357 * This is the number of bytes per line. It may be >0 or <0 depending on
358 * whether this is a top-down or bottom-up image.
359 * - dstbits
360 * Same as srcbits but for the destination
361 * - dstlinebytes
362 * Same as srclinebytes but for the destination.
364 * Notes:
365 * - The supported Dib formats are: pal1, pal4, pal8, rgb555, bgr555,
366 * rgb565, bgr565, rgb888 and any 32bit (0888) format.
367 * The supported XImage (Bmp) formats are: pal1, pal4, pal8,
368 * rgb555, bgr555, rgb565, bgr565, rgb888, bgr888, rgb0888, bgr0888.
369 * - Rgb formats are those for which the masks are such that:
370 * red_mask > green_mask > blue_mask
371 * - Bgr formats are those for which the masks sort in the other direction.
372 * - Many conversion functions handle both rgb->bgr and bgr->rgb conversions
373 * so the comments use h, g, l to mean respectively the source color in the
374 * high bits, the green, and the source color in the low bits.
376 static void X11DRV_DIB_Convert_any_asis(int width, int height,
377 int bytes_per_pixel,
378 const void* srcbits, int srclinebytes,
379 void* dstbits, int dstlinebytes)
381 int y;
383 width*=bytes_per_pixel;
384 for (y=0; y<height; y++) {
385 memcpy(dstbits, srcbits, width);
386 srcbits = (char*)srcbits + srclinebytes;
387 dstbits = (char*)dstbits + dstlinebytes;
392 * 15 bit conversions
395 static void X11DRV_DIB_Convert_555_reverse(int width, int height,
396 const void* srcbits, int srclinebytes,
397 void* dstbits, int dstlinebytes)
399 const DWORD* srcpixel;
400 DWORD* dstpixel;
401 int x,y;
403 for (y=0; y<height; y++) {
404 srcpixel=srcbits;
405 dstpixel=dstbits;
406 for (x=0; x<width/2; x++) {
407 /* Do 2 pixels at a time */
408 DWORD srcval;
409 srcval=*srcpixel++;
410 *dstpixel++=((srcval << 10) & 0x7c007c00) | /* h */
411 ( srcval & 0x03e003e0) | /* g */
412 ((srcval >> 10) & 0x001f001f); /* l */
414 if (width&1) {
415 /* And the the odd pixel */
416 WORD srcval;
417 srcval=*((WORD*)srcpixel);
418 *((WORD*)dstpixel)=((srcval << 10) & 0x7c00) | /* h */
419 ( srcval & 0x03e0) | /* g */
420 ((srcval >> 10) & 0x001f); /* l */
422 srcbits = (char*)srcbits + srclinebytes;
423 dstbits = (char*)dstbits + dstlinebytes;
427 static void X11DRV_DIB_Convert_555_to_565_asis(int width, int height,
428 const void* srcbits, int srclinebytes,
429 void* dstbits, int dstlinebytes)
431 const DWORD* srcpixel;
432 DWORD* dstpixel;
433 int x,y;
435 for (y=0; y<height; y++) {
436 srcpixel=srcbits;
437 dstpixel=dstbits;
438 for (x=0; x<width/2; x++) {
439 /* Do 2 pixels at a time */
440 DWORD srcval;
441 srcval=*srcpixel++;
442 *dstpixel++=((srcval << 1) & 0xffc0ffc0) | /* h, g */
443 ((srcval >> 4) & 0x00200020) | /* g - 1 bit */
444 ( srcval & 0x001f001f); /* l */
446 if (width&1) {
447 /* And the the odd pixel */
448 WORD srcval;
449 srcval=*((WORD*)srcpixel);
450 *((WORD*)dstpixel)=((srcval << 1) & 0xffc0) | /* h, g */
451 ((srcval >> 4) & 0x0020) | /* g - 1 bit */
452 (srcval & 0x001f); /* l */
454 srcbits = (char*)srcbits + srclinebytes;
455 dstbits = (char*)dstbits + dstlinebytes;
459 static void X11DRV_DIB_Convert_555_to_565_reverse(int width, int height,
460 const void* srcbits, int srclinebytes,
461 void* dstbits, int dstlinebytes)
463 const DWORD* srcpixel;
464 DWORD* dstpixel;
465 int x,y;
467 for (y=0; y<height; y++) {
468 srcpixel=srcbits;
469 dstpixel=dstbits;
470 for (x=0; x<width/2; x++) {
471 /* Do 2 pixels at a time */
472 DWORD srcval;
473 srcval=*srcpixel++;
474 *dstpixel++=((srcval >> 10) & 0x001f001f) | /* h */
475 ((srcval << 1) & 0x07c007c0) | /* g */
476 ((srcval >> 4) & 0x00200020) | /* g - 1 bit */
477 ((srcval << 11) & 0xf800f800); /* l */
479 if (width&1) {
480 /* And the the odd pixel */
481 WORD srcval;
482 srcval=*((WORD*)srcpixel);
483 *((WORD*)dstpixel)=((srcval >> 10) & 0x001f) | /* h */
484 ((srcval << 1) & 0x07c0) | /* g */
485 ((srcval >> 4) & 0x0020) | /* g - 1 bit */
486 ((srcval << 11) & 0xf800); /* l */
488 srcbits = (char*)srcbits + srclinebytes;
489 dstbits = (char*)dstbits + dstlinebytes;
493 static void X11DRV_DIB_Convert_555_to_888_asis(int width, int height,
494 const void* srcbits, int srclinebytes,
495 void* dstbits, int dstlinebytes)
497 const WORD* srcpixel;
498 BYTE* dstpixel;
499 int x,y;
501 for (y=0; y<height; y++) {
502 srcpixel=srcbits;
503 dstpixel=dstbits;
504 for (x=0; x<width; x++) {
505 WORD srcval;
506 srcval=*srcpixel++;
507 dstpixel[0]=((srcval << 3) & 0xf8) | /* l */
508 ((srcval >> 2) & 0x07); /* l - 3 bits */
509 dstpixel[1]=((srcval >> 2) & 0xf8) | /* g */
510 ((srcval >> 7) & 0x07); /* g - 3 bits */
511 dstpixel[2]=((srcval >> 7) & 0xf8) | /* h */
512 ((srcval >> 12) & 0x07); /* h - 3 bits */
513 dstpixel+=3;
515 srcbits = (char*)srcbits + srclinebytes;
516 dstbits = (char*)dstbits + dstlinebytes;
520 static void X11DRV_DIB_Convert_555_to_888_reverse(int width, int height,
521 const void* srcbits, int srclinebytes,
522 void* dstbits, int dstlinebytes)
524 const WORD* srcpixel;
525 BYTE* dstpixel;
526 int x,y;
528 for (y=0; y<height; y++) {
529 srcpixel=srcbits;
530 dstpixel=dstbits;
531 for (x=0; x<width; x++) {
532 WORD srcval;
533 srcval=*srcpixel++;
534 dstpixel[0]=((srcval >> 7) & 0xf8) | /* h */
535 ((srcval >> 12) & 0x07); /* h - 3 bits */
536 dstpixel[1]=((srcval >> 2) & 0xf8) | /* g */
537 ((srcval >> 7) & 0x07); /* g - 3 bits */
538 dstpixel[2]=((srcval << 3) & 0xf8) | /* l */
539 ((srcval >> 2) & 0x07); /* l - 3 bits */
540 dstpixel+=3;
542 srcbits = (char*)srcbits + srclinebytes;
543 dstbits = (char*)dstbits + dstlinebytes;
547 static void X11DRV_DIB_Convert_555_to_0888_asis(int width, int height,
548 const void* srcbits, int srclinebytes,
549 void* dstbits, int dstlinebytes)
551 const WORD* srcpixel;
552 DWORD* dstpixel;
553 int x,y;
555 for (y=0; y<height; y++) {
556 srcpixel=srcbits;
557 dstpixel=dstbits;
558 for (x=0; x<width; x++) {
559 WORD srcval;
560 srcval=*srcpixel++;
561 *dstpixel++=((srcval << 9) & 0xf80000) | /* h */
562 ((srcval << 4) & 0x070000) | /* h - 3 bits */
563 ((srcval << 6) & 0x00f800) | /* g */
564 ((srcval << 1) & 0x000700) | /* g - 3 bits */
565 ((srcval << 3) & 0x0000f8) | /* l */
566 ((srcval >> 2) & 0x000007); /* l - 3 bits */
568 srcbits = (char*)srcbits + srclinebytes;
569 dstbits = (char*)dstbits + dstlinebytes;
573 static void X11DRV_DIB_Convert_555_to_0888_reverse(int width, int height,
574 const void* srcbits, int srclinebytes,
575 void* dstbits, int dstlinebytes)
577 const WORD* srcpixel;
578 DWORD* dstpixel;
579 int x,y;
581 for (y=0; y<height; y++) {
582 srcpixel=srcbits;
583 dstpixel=dstbits;
584 for (x=0; x<width; x++) {
585 WORD srcval;
586 srcval=*srcpixel++;
587 *dstpixel++=((srcval >> 7) & 0x0000f8) | /* h */
588 ((srcval >> 12) & 0x000007) | /* h - 3 bits */
589 ((srcval << 6) & 0x00f800) | /* g */
590 ((srcval << 1) & 0x000700) | /* g - 3 bits */
591 ((srcval << 19) & 0xf80000) | /* l */
592 ((srcval << 14) & 0x070000); /* l - 3 bits */
594 srcbits = (char*)srcbits + srclinebytes;
595 dstbits = (char*)dstbits + dstlinebytes;
599 static void X11DRV_DIB_Convert_5x5_to_any0888(int width, int height,
600 const void* srcbits, int srclinebytes,
601 WORD rsrc, WORD gsrc, WORD bsrc,
602 void* dstbits, int dstlinebytes,
603 DWORD rdst, DWORD gdst, DWORD bdst)
605 int rRightShift1,gRightShift1,bRightShift1;
606 int rRightShift2,gRightShift2,bRightShift2;
607 BYTE gMask1,gMask2;
608 int rLeftShift,gLeftShift,bLeftShift;
609 const WORD* srcpixel;
610 DWORD* dstpixel;
611 int x,y;
613 /* Note, the source pixel value is shifted left by 16 bits so that
614 * we know we will always have to shift right to extract the components.
616 rRightShift1=16+X11DRV_DIB_MaskToShift(rsrc)-3;
617 gRightShift1=16+X11DRV_DIB_MaskToShift(gsrc)-3;
618 bRightShift1=16+X11DRV_DIB_MaskToShift(bsrc)-3;
619 rRightShift2=rRightShift1+5;
620 gRightShift2=gRightShift1+5;
621 bRightShift2=bRightShift1+5;
622 if (gsrc==0x03e0) {
623 /* Green has 5 bits, like the others */
624 gMask1=0xf8;
625 gMask2=0x07;
626 } else {
627 /* Green has 6 bits, not 5. Compensate. */
628 gRightShift1++;
629 gRightShift2+=2;
630 gMask1=0xfc;
631 gMask2=0x03;
634 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
635 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
636 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
638 for (y=0; y<height; y++) {
639 srcpixel=srcbits;
640 dstpixel=dstbits;
641 for (x=0; x<width; x++) {
642 DWORD srcval;
643 BYTE red,green,blue;
644 srcval=*srcpixel++ << 16;
645 red= ((srcval >> rRightShift1) & 0xf8) |
646 ((srcval >> rRightShift2) & 0x07);
647 green=((srcval >> gRightShift1) & gMask1) |
648 ((srcval >> gRightShift2) & gMask2);
649 blue= ((srcval >> bRightShift1) & 0xf8) |
650 ((srcval >> bRightShift2) & 0x07);
651 *dstpixel++=(red << rLeftShift) |
652 (green << gLeftShift) |
653 (blue << bLeftShift);
655 srcbits = (char*)srcbits + srclinebytes;
656 dstbits = (char*)dstbits + dstlinebytes;
661 * 16 bits conversions
664 static void X11DRV_DIB_Convert_565_reverse(int width, int height,
665 const void* srcbits, int srclinebytes,
666 void* dstbits, int dstlinebytes)
668 const DWORD* srcpixel;
669 DWORD* dstpixel;
670 int x,y;
672 for (y=0; y<height; y++) {
673 srcpixel=srcbits;
674 dstpixel=dstbits;
675 for (x=0; x<width/2; x++) {
676 /* Do 2 pixels at a time */
677 DWORD srcval;
678 srcval=*srcpixel++;
679 *dstpixel++=((srcval << 11) & 0xf800f800) | /* h */
680 ( srcval & 0x07e007e0) | /* g */
681 ((srcval >> 11) & 0x001f001f); /* l */
683 if (width&1) {
684 /* And the the odd pixel */
685 WORD srcval;
686 srcval=*((WORD*)srcpixel);
687 *((WORD*)dstpixel)=((srcval << 11) & 0xf800) | /* h */
688 ( srcval & 0x07e0) | /* g */
689 ((srcval >> 11) & 0x001f); /* l */
691 srcbits = (char*)srcbits + srclinebytes;
692 dstbits = (char*)dstbits + dstlinebytes;
696 static void X11DRV_DIB_Convert_565_to_555_asis(int width, int height,
697 const void* srcbits, int srclinebytes,
698 void* dstbits, int dstlinebytes)
700 const DWORD* srcpixel;
701 DWORD* dstpixel;
702 int x,y;
704 for (y=0; y<height; y++) {
705 srcpixel=srcbits;
706 dstpixel=dstbits;
707 for (x=0; x<width/2; x++) {
708 /* Do 2 pixels at a time */
709 DWORD srcval;
710 srcval=*srcpixel++;
711 *dstpixel++=((srcval >> 1) & 0x7fe07fe0) | /* h, g */
712 ( srcval & 0x001f001f); /* l */
714 if (width&1) {
715 /* And the the odd pixel */
716 WORD srcval;
717 srcval=*((WORD*)srcpixel);
718 *((WORD*)dstpixel)=((srcval >> 1) & 0x7fe0) | /* h, g */
719 ( srcval & 0x001f); /* l */
721 srcbits = (char*)srcbits + srclinebytes;
722 dstbits = (char*)dstbits + dstlinebytes;
726 static void X11DRV_DIB_Convert_565_to_555_reverse(int width, int height,
727 const void* srcbits, int srclinebytes,
728 void* dstbits, int dstlinebytes)
730 const DWORD* srcpixel;
731 DWORD* dstpixel;
732 int x,y;
734 for (y=0; y<height; y++) {
735 srcpixel=srcbits;
736 dstpixel=dstbits;
737 for (x=0; x<width/2; x++) {
738 /* Do 2 pixels at a time */
739 DWORD srcval;
740 srcval=*srcpixel++;
741 *dstpixel++=((srcval >> 11) & 0x001f001f) | /* h */
742 ((srcval >> 1) & 0x03e003e0) | /* g */
743 ((srcval << 10) & 0x7c007c00); /* l */
745 if (width&1) {
746 /* And the the odd pixel */
747 WORD srcval;
748 srcval=*((WORD*)srcpixel);
749 *((WORD*)dstpixel)=((srcval >> 11) & 0x001f) | /* h */
750 ((srcval >> 1) & 0x03e0) | /* g */
751 ((srcval << 10) & 0x7c00); /* l */
753 srcbits = (char*)srcbits + srclinebytes;
754 dstbits = (char*)dstbits + dstlinebytes;
758 static void X11DRV_DIB_Convert_565_to_888_asis(int width, int height,
759 const void* srcbits, int srclinebytes,
760 void* dstbits, int dstlinebytes)
762 const WORD* srcpixel;
763 BYTE* dstpixel;
764 int x,y;
766 for (y=0; y<height; y++) {
767 srcpixel=srcbits;
768 dstpixel=dstbits;
769 for (x=0; x<width; x++) {
770 WORD srcval;
771 srcval=*srcpixel++;
772 dstpixel[0]=((srcval << 3) & 0xf8) | /* l */
773 ((srcval >> 2) & 0x07); /* l - 3 bits */
774 dstpixel[1]=((srcval >> 3) & 0xfc) | /* g */
775 ((srcval >> 9) & 0x03); /* g - 2 bits */
776 dstpixel[2]=((srcval >> 8) & 0xf8) | /* h */
777 ((srcval >> 13) & 0x07); /* h - 3 bits */
778 dstpixel+=3;
780 srcbits = (char*)srcbits + srclinebytes;
781 dstbits = (char*)dstbits + dstlinebytes;
785 static void X11DRV_DIB_Convert_565_to_888_reverse(int width, int height,
786 const void* srcbits, int srclinebytes,
787 void* dstbits, int dstlinebytes)
789 const WORD* srcpixel;
790 BYTE* dstpixel;
791 int x,y;
793 for (y=0; y<height; y++) {
794 srcpixel=srcbits;
795 dstpixel=dstbits;
796 for (x=0; x<width; x++) {
797 WORD srcval;
798 srcval=*srcpixel++;
799 dstpixel[0]=((srcval >> 8) & 0xf8) | /* h */
800 ((srcval >> 13) & 0x07); /* h - 3 bits */
801 dstpixel[1]=((srcval >> 3) & 0xfc) | /* g */
802 ((srcval >> 9) & 0x03); /* g - 2 bits */
803 dstpixel[2]=((srcval << 3) & 0xf8) | /* l */
804 ((srcval >> 2) & 0x07); /* l - 3 bits */
805 dstpixel+=3;
807 srcbits = (char*)srcbits + srclinebytes;
808 dstbits = (char*)dstbits + dstlinebytes;
812 static void X11DRV_DIB_Convert_565_to_0888_asis(int width, int height,
813 const void* srcbits, int srclinebytes,
814 void* dstbits, int dstlinebytes)
816 const WORD* srcpixel;
817 DWORD* dstpixel;
818 int x,y;
820 for (y=0; y<height; y++) {
821 srcpixel=srcbits;
822 dstpixel=dstbits;
823 for (x=0; x<width; x++) {
824 WORD srcval;
825 srcval=*srcpixel++;
826 *dstpixel++=((srcval << 8) & 0xf80000) | /* h */
827 ((srcval << 3) & 0x070000) | /* h - 3 bits */
828 ((srcval << 5) & 0x00fc00) | /* g */
829 ((srcval >> 1) & 0x000300) | /* g - 2 bits */
830 ((srcval << 3) & 0x0000f8) | /* l */
831 ((srcval >> 2) & 0x000007); /* l - 3 bits */
833 srcbits = (char*)srcbits + srclinebytes;
834 dstbits = (char*)dstbits + dstlinebytes;
838 static void X11DRV_DIB_Convert_565_to_0888_reverse(int width, int height,
839 const void* srcbits, int srclinebytes,
840 void* dstbits, int dstlinebytes)
842 const WORD* srcpixel;
843 DWORD* dstpixel;
844 int x,y;
846 for (y=0; y<height; y++) {
847 srcpixel=srcbits;
848 dstpixel=dstbits;
849 for (x=0; x<width; x++) {
850 WORD srcval;
851 srcval=*srcpixel++;
852 *dstpixel++=((srcval >> 8) & 0x0000f8) | /* h */
853 ((srcval >> 13) & 0x000007) | /* h - 3 bits */
854 ((srcval << 5) & 0x00fc00) | /* g */
855 ((srcval >> 1) & 0x000300) | /* g - 2 bits */
856 ((srcval << 19) & 0xf80000) | /* l */
857 ((srcval << 14) & 0x070000); /* l - 3 bits */
859 srcbits = (char*)srcbits + srclinebytes;
860 dstbits = (char*)dstbits + dstlinebytes;
865 * 24 bit conversions
868 static void X11DRV_DIB_Convert_888_reverse(int width, int height,
869 const void* srcbits, int srclinebytes,
870 void* dstbits, int dstlinebytes)
872 const BYTE* srcpixel;
873 BYTE* dstpixel;
874 int x,y;
876 for (y=0; y<height; y++) {
877 srcpixel=srcbits;
878 dstpixel=dstbits;
879 for (x=0; x<width; x++) {
880 dstpixel[0]=srcpixel[2];
881 dstpixel[1]=srcpixel[1];
882 dstpixel[2]=srcpixel[0];
883 srcpixel+=3;
884 dstpixel+=3;
886 srcbits = (char*)srcbits + srclinebytes;
887 dstbits = (char*)dstbits + dstlinebytes;
891 static void X11DRV_DIB_Convert_888_to_555_asis(int width, int height,
892 const void* srcbits, int srclinebytes,
893 void* dstbits, int dstlinebytes)
895 const DWORD* srcpixel;
896 const BYTE* srcbyte;
897 WORD* dstpixel;
898 int x,y;
899 int oddwidth;
901 oddwidth=width & 3;
902 width=width/4;
903 for (y=0; y<height; y++) {
904 srcpixel=srcbits;
905 dstpixel=dstbits;
906 for (x=0; x<width; x++) {
907 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
908 DWORD srcval1,srcval2;
909 srcval1=srcpixel[0];
910 dstpixel[0]=((srcval1 >> 3) & 0x001f) | /* l1 */
911 ((srcval1 >> 6) & 0x03e0) | /* g1 */
912 ((srcval1 >> 9) & 0x7c00); /* h1 */
913 srcval2=srcpixel[1];
914 dstpixel[1]=((srcval1 >> 27) & 0x001f) | /* l2 */
915 ((srcval2 << 2) & 0x03e0) | /* g2 */
916 ((srcval2 >> 1) & 0x7c00); /* h2 */
917 srcval1=srcpixel[2];
918 dstpixel[2]=((srcval2 >> 19) & 0x001f) | /* l3 */
919 ((srcval2 >> 22) & 0x03e0) | /* g3 */
920 ((srcval1 << 7) & 0x7c00); /* h3 */
921 dstpixel[3]=((srcval1 >> 11) & 0x001f) | /* l4 */
922 ((srcval1 >> 14) & 0x03e0) | /* g4 */
923 ((srcval1 >> 17) & 0x7c00); /* h4 */
924 srcpixel+=3;
925 dstpixel+=4;
927 /* And now up to 3 odd pixels */
928 srcbyte=(LPBYTE)srcpixel;
929 for (x=0; x<oddwidth; x++) {
930 WORD dstval;
931 dstval =((srcbyte[0] >> 3) & 0x001f); /* l */
932 dstval|=((srcbyte[1] << 2) & 0x03e0); /* g */
933 dstval|=((srcbyte[2] << 7) & 0x7c00); /* h */
934 *dstpixel++=dstval;
935 srcbyte+=3;
937 srcbits = (char*)srcbits + srclinebytes;
938 dstbits = (char*)dstbits + dstlinebytes;
942 static void X11DRV_DIB_Convert_888_to_555_reverse(int width, int height,
943 const void* srcbits, int srclinebytes,
944 void* dstbits, int dstlinebytes)
946 const DWORD* srcpixel;
947 const BYTE* srcbyte;
948 WORD* dstpixel;
949 int x,y;
950 int oddwidth;
952 oddwidth=width & 3;
953 width=width/4;
954 for (y=0; y<height; y++) {
955 srcpixel=srcbits;
956 dstpixel=dstbits;
957 for (x=0; x<width; x++) {
958 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
959 DWORD srcval1,srcval2;
960 srcval1=srcpixel[0];
961 dstpixel[0]=((srcval1 << 7) & 0x7c00) | /* l1 */
962 ((srcval1 >> 6) & 0x03e0) | /* g1 */
963 ((srcval1 >> 19) & 0x001f); /* h1 */
964 srcval2=srcpixel[1];
965 dstpixel[1]=((srcval1 >> 17) & 0x7c00) | /* l2 */
966 ((srcval2 << 2) & 0x03e0) | /* g2 */
967 ((srcval2 >> 11) & 0x001f); /* h2 */
968 srcval1=srcpixel[2];
969 dstpixel[2]=((srcval2 >> 9) & 0x7c00) | /* l3 */
970 ((srcval2 >> 22) & 0x03e0) | /* g3 */
971 ((srcval1 >> 3) & 0x001f); /* h3 */
972 dstpixel[3]=((srcval1 >> 1) & 0x7c00) | /* l4 */
973 ((srcval1 >> 14) & 0x03e0) | /* g4 */
974 ((srcval1 >> 27) & 0x001f); /* h4 */
975 srcpixel+=3;
976 dstpixel+=4;
978 /* And now up to 3 odd pixels */
979 srcbyte=(LPBYTE)srcpixel;
980 for (x=0; x<oddwidth; x++) {
981 WORD dstval;
982 dstval =((srcbyte[0] << 7) & 0x7c00); /* l */
983 dstval|=((srcbyte[1] << 2) & 0x03e0); /* g */
984 dstval|=((srcbyte[2] >> 3) & 0x001f); /* h */
985 *dstpixel++=dstval;
986 srcbyte+=3;
988 srcbits = (char*)srcbits + srclinebytes;
989 dstbits = (char*)dstbits + dstlinebytes;
993 static void X11DRV_DIB_Convert_888_to_565_asis(int width, int height,
994 const void* srcbits, int srclinebytes,
995 void* dstbits, int dstlinebytes)
997 const DWORD* srcpixel;
998 const BYTE* srcbyte;
999 WORD* dstpixel;
1000 int x,y;
1001 int oddwidth;
1003 oddwidth=width & 3;
1004 width=width/4;
1005 for (y=0; y<height; y++) {
1006 srcpixel=srcbits;
1007 dstpixel=dstbits;
1008 for (x=0; x<width; x++) {
1009 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
1010 DWORD srcval1,srcval2;
1011 srcval1=srcpixel[0];
1012 dstpixel[0]=((srcval1 >> 3) & 0x001f) | /* l1 */
1013 ((srcval1 >> 5) & 0x07e0) | /* g1 */
1014 ((srcval1 >> 8) & 0xf800); /* h1 */
1015 srcval2=srcpixel[1];
1016 dstpixel[1]=((srcval1 >> 27) & 0x001f) | /* l2 */
1017 ((srcval2 << 3) & 0x07e0) | /* g2 */
1018 ( srcval2 & 0xf800); /* h2 */
1019 srcval1=srcpixel[2];
1020 dstpixel[2]=((srcval2 >> 19) & 0x001f) | /* l3 */
1021 ((srcval2 >> 21) & 0x07e0) | /* g3 */
1022 ((srcval1 << 8) & 0xf800); /* h3 */
1023 dstpixel[3]=((srcval1 >> 11) & 0x001f) | /* l4 */
1024 ((srcval1 >> 13) & 0x07e0) | /* g4 */
1025 ((srcval1 >> 16) & 0xf800); /* h4 */
1026 srcpixel+=3;
1027 dstpixel+=4;
1029 /* And now up to 3 odd pixels */
1030 srcbyte=(LPBYTE)srcpixel;
1031 for (x=0; x<oddwidth; x++) {
1032 WORD dstval;
1033 dstval =((srcbyte[0] >> 3) & 0x001f); /* l */
1034 dstval|=((srcbyte[1] << 3) & 0x07e0); /* g */
1035 dstval|=((srcbyte[2] << 8) & 0xf800); /* h */
1036 *dstpixel++=dstval;
1037 srcbyte+=3;
1039 srcbits = (char*)srcbits + srclinebytes;
1040 dstbits = (char*)dstbits + dstlinebytes;
1044 static void X11DRV_DIB_Convert_888_to_565_reverse(int width, int height,
1045 const void* srcbits, int srclinebytes,
1046 void* dstbits, int dstlinebytes)
1048 const DWORD* srcpixel;
1049 const BYTE* srcbyte;
1050 WORD* dstpixel;
1051 int x,y;
1052 int oddwidth;
1054 oddwidth=width & 3;
1055 width=width/4;
1056 for (y=0; y<height; y++) {
1057 srcpixel=srcbits;
1058 dstpixel=dstbits;
1059 for (x=0; x<width; x++) {
1060 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
1061 DWORD srcval1,srcval2;
1062 srcval1=srcpixel[0];
1063 dstpixel[0]=((srcval1 << 8) & 0xf800) | /* l1 */
1064 ((srcval1 >> 5) & 0x07e0) | /* g1 */
1065 ((srcval1 >> 19) & 0x001f); /* h1 */
1066 srcval2=srcpixel[1];
1067 dstpixel[1]=((srcval1 >> 16) & 0xf800) | /* l2 */
1068 ((srcval2 << 3) & 0x07e0) | /* g2 */
1069 ((srcval2 >> 11) & 0x001f); /* h2 */
1070 srcval1=srcpixel[2];
1071 dstpixel[2]=((srcval2 >> 8) & 0xf800) | /* l3 */
1072 ((srcval2 >> 21) & 0x07e0) | /* g3 */
1073 ((srcval1 >> 3) & 0x001f); /* h3 */
1074 dstpixel[3]=(srcval1 & 0xf800) | /* l4 */
1075 ((srcval1 >> 13) & 0x07e0) | /* g4 */
1076 ((srcval1 >> 27) & 0x001f); /* h4 */
1077 srcpixel+=3;
1078 dstpixel+=4;
1080 /* And now up to 3 odd pixels */
1081 srcbyte=(LPBYTE)srcpixel;
1082 for (x=0; x<oddwidth; x++) {
1083 WORD dstval;
1084 dstval =((srcbyte[0] << 8) & 0xf800); /* l */
1085 dstval|=((srcbyte[1] << 3) & 0x07e0); /* g */
1086 dstval|=((srcbyte[2] >> 3) & 0x001f); /* h */
1087 *dstpixel++=dstval;
1088 srcbyte+=3;
1090 srcbits = (char*)srcbits + srclinebytes;
1091 dstbits = (char*)dstbits + dstlinebytes;
1095 static void X11DRV_DIB_Convert_888_to_0888_asis(int width, int height,
1096 const void* srcbits, int srclinebytes,
1097 void* dstbits, int dstlinebytes)
1099 const DWORD* srcpixel;
1100 DWORD* dstpixel;
1101 int x,y;
1102 int oddwidth;
1104 oddwidth=width & 3;
1105 width=width/4;
1106 for (y=0; y<height; y++) {
1107 srcpixel=srcbits;
1108 dstpixel=dstbits;
1109 for (x=0; x<width; x++) {
1110 /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
1111 DWORD srcval1,srcval2;
1112 srcval1=srcpixel[0];
1113 dstpixel[0]=( srcval1 & 0x00ffffff); /* h1, g1, l1 */
1114 srcval2=srcpixel[1];
1115 dstpixel[1]=( srcval1 >> 24) | /* l2 */
1116 ((srcval2 << 8) & 0x00ffff00); /* h2, g2 */
1117 srcval1=srcpixel[2];
1118 dstpixel[2]=( srcval2 >> 16) | /* g3, l3 */
1119 ((srcval1 << 16) & 0x00ff0000); /* h3 */
1120 dstpixel[3]=( srcval1 >> 8); /* h4, g4, l4 */
1121 srcpixel+=3;
1122 dstpixel+=4;
1124 /* And now up to 3 odd pixels */
1125 for (x=0; x<oddwidth; x++) {
1126 DWORD srcval;
1127 srcval=*srcpixel;
1128 srcpixel=(LPDWORD)(((char*)srcpixel)+3);
1129 *dstpixel++=( srcval & 0x00ffffff); /* h, g, l */
1131 srcbits = (char*)srcbits + srclinebytes;
1132 dstbits = (char*)dstbits + dstlinebytes;
1136 static void X11DRV_DIB_Convert_888_to_0888_reverse(int width, int height,
1137 const void* srcbits, int srclinebytes,
1138 void* dstbits, int dstlinebytes)
1140 const DWORD* srcpixel;
1141 DWORD* dstpixel;
1142 int x,y;
1143 int oddwidth;
1145 oddwidth=width & 3;
1146 width=width/4;
1147 for (y=0; y<height; y++) {
1148 srcpixel=srcbits;
1149 dstpixel=dstbits;
1150 for (x=0; x<width; x++) {
1151 /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
1152 DWORD srcval1,srcval2;
1154 srcval1=srcpixel[0];
1155 dstpixel[0]=((srcval1 >> 16) & 0x0000ff) | /* h1 */
1156 ( srcval1 & 0x00ff00) | /* g1 */
1157 ((srcval1 << 16) & 0xff0000); /* l1 */
1158 srcval2=srcpixel[1];
1159 dstpixel[1]=((srcval1 >> 8) & 0xff0000) | /* l2 */
1160 ((srcval2 << 8) & 0x00ff00) | /* g2 */
1161 ((srcval2 >> 8) & 0x0000ff); /* h2 */
1162 srcval1=srcpixel[2];
1163 dstpixel[2]=( srcval2 & 0xff0000) | /* l3 */
1164 ((srcval2 >> 16) & 0x00ff00) | /* g3 */
1165 ( srcval1 & 0x0000ff); /* h3 */
1166 dstpixel[3]=((srcval1 >> 24) & 0x0000ff) | /* h4 */
1167 ((srcval1 >> 8) & 0x00ff00) | /* g4 */
1168 ((srcval1 << 8) & 0xff0000); /* l4 */
1169 srcpixel+=3;
1170 dstpixel+=4;
1172 /* And now up to 3 odd pixels */
1173 for (x=0; x<oddwidth; x++) {
1174 DWORD srcval;
1175 srcval=*srcpixel;
1176 srcpixel=(LPDWORD)(((char*)srcpixel)+3);
1177 *dstpixel++=((srcval >> 16) & 0x0000ff) | /* h */
1178 ( srcval & 0x00ff00) | /* g */
1179 ((srcval << 16) & 0xff0000); /* l */
1181 srcbits = (char*)srcbits + srclinebytes;
1182 dstbits = (char*)dstbits + dstlinebytes;
1186 static void X11DRV_DIB_Convert_rgb888_to_any0888(int width, int height,
1187 const void* srcbits, int srclinebytes,
1188 void* dstbits, int dstlinebytes,
1189 DWORD rdst, DWORD gdst, DWORD bdst)
1191 int rLeftShift,gLeftShift,bLeftShift;
1192 const BYTE* srcpixel;
1193 DWORD* dstpixel;
1194 int x,y;
1196 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1197 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1198 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1199 for (y=0; y<height; y++) {
1200 srcpixel=srcbits;
1201 dstpixel=dstbits;
1202 for (x=0; x<width; x++) {
1203 *dstpixel++=(srcpixel[0] << bLeftShift) | /* b */
1204 (srcpixel[1] << gLeftShift) | /* g */
1205 (srcpixel[2] << rLeftShift); /* r */
1206 srcpixel+=3;
1208 srcbits = (char*)srcbits + srclinebytes;
1209 dstbits = (char*)dstbits + dstlinebytes;
1213 static void X11DRV_DIB_Convert_bgr888_to_any0888(int width, int height,
1214 const void* srcbits, int srclinebytes,
1215 void* dstbits, int dstlinebytes,
1216 DWORD rdst, DWORD gdst, DWORD bdst)
1218 int rLeftShift,gLeftShift,bLeftShift;
1219 const BYTE* srcpixel;
1220 DWORD* dstpixel;
1221 int x,y;
1223 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1224 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1225 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1226 for (y=0; y<height; y++) {
1227 srcpixel=srcbits;
1228 dstpixel=dstbits;
1229 for (x=0; x<width; x++) {
1230 *dstpixel++=(srcpixel[0] << rLeftShift) | /* r */
1231 (srcpixel[1] << gLeftShift) | /* g */
1232 (srcpixel[2] << bLeftShift); /* b */
1233 srcpixel+=3;
1235 srcbits = (char*)srcbits + srclinebytes;
1236 dstbits = (char*)dstbits + dstlinebytes;
1241 * 32 bit conversions
1244 static void X11DRV_DIB_Convert_0888_reverse(int width, int height,
1245 const void* srcbits, int srclinebytes,
1246 void* dstbits, int dstlinebytes)
1248 const DWORD* srcpixel;
1249 DWORD* dstpixel;
1250 int x,y;
1252 for (y=0; y<height; y++) {
1253 srcpixel=srcbits;
1254 dstpixel=dstbits;
1255 for (x=0; x<width; x++) {
1256 DWORD srcval;
1257 srcval=*srcpixel++;
1258 *dstpixel++=((srcval << 16) & 0x00ff0000) | /* h */
1259 ( srcval & 0x0000ff00) | /* g */
1260 ((srcval >> 16) & 0x000000ff); /* l */
1262 srcbits = (char*)srcbits + srclinebytes;
1263 dstbits = (char*)dstbits + dstlinebytes;
1267 static void X11DRV_DIB_Convert_0888_any(int width, int height,
1268 const void* srcbits, int srclinebytes,
1269 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1270 void* dstbits, int dstlinebytes,
1271 DWORD rdst, DWORD gdst, DWORD bdst)
1273 int rRightShift,gRightShift,bRightShift;
1274 int rLeftShift,gLeftShift,bLeftShift;
1275 const DWORD* srcpixel;
1276 DWORD* dstpixel;
1277 int x,y;
1279 rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1280 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1281 bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1282 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1283 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1284 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1285 for (y=0; y<height; y++) {
1286 srcpixel=srcbits;
1287 dstpixel=dstbits;
1288 for (x=0; x<width; x++) {
1289 DWORD srcval;
1290 srcval=*srcpixel++;
1291 *dstpixel++=(((srcval >> rRightShift) & 0xff) << rLeftShift) |
1292 (((srcval >> gRightShift) & 0xff) << gLeftShift) |
1293 (((srcval >> bRightShift) & 0xff) << bLeftShift);
1295 srcbits = (char*)srcbits + srclinebytes;
1296 dstbits = (char*)dstbits + dstlinebytes;
1300 static void X11DRV_DIB_Convert_0888_to_555_asis(int width, int height,
1301 const void* srcbits, int srclinebytes,
1302 void* dstbits, int dstlinebytes)
1304 const DWORD* srcpixel;
1305 WORD* dstpixel;
1306 int x,y;
1308 for (y=0; y<height; y++) {
1309 srcpixel=srcbits;
1310 dstpixel=dstbits;
1311 for (x=0; x<width; x++) {
1312 DWORD srcval;
1313 srcval=*srcpixel++;
1314 *dstpixel++=((srcval >> 9) & 0x7c00) | /* h */
1315 ((srcval >> 6) & 0x03e0) | /* g */
1316 ((srcval >> 3) & 0x001f); /* l */
1318 srcbits = (char*)srcbits + srclinebytes;
1319 dstbits = (char*)dstbits + dstlinebytes;
1323 static void X11DRV_DIB_Convert_0888_to_555_reverse(int width, int height,
1324 const void* srcbits, int srclinebytes,
1325 void* dstbits, int dstlinebytes)
1327 const DWORD* srcpixel;
1328 WORD* dstpixel;
1329 int x,y;
1331 for (y=0; y<height; y++) {
1332 srcpixel=srcbits;
1333 dstpixel=dstbits;
1334 for (x=0; x<width; x++) {
1335 DWORD srcval;
1336 srcval=*srcpixel++;
1337 *dstpixel++=((srcval >> 19) & 0x001f) | /* h */
1338 ((srcval >> 6) & 0x03e0) | /* g */
1339 ((srcval << 7) & 0x7c00); /* l */
1341 srcbits = (char*)srcbits + srclinebytes;
1342 dstbits = (char*)dstbits + dstlinebytes;
1346 static void X11DRV_DIB_Convert_0888_to_565_asis(int width, int height,
1347 const void* srcbits, int srclinebytes,
1348 void* dstbits, int dstlinebytes)
1350 const DWORD* srcpixel;
1351 WORD* dstpixel;
1352 int x,y;
1354 for (y=0; y<height; y++) {
1355 srcpixel=srcbits;
1356 dstpixel=dstbits;
1357 for (x=0; x<width; x++) {
1358 DWORD srcval;
1359 srcval=*srcpixel++;
1360 *dstpixel++=((srcval >> 8) & 0xf800) | /* h */
1361 ((srcval >> 5) & 0x07e0) | /* g */
1362 ((srcval >> 3) & 0x001f); /* l */
1364 srcbits = (char*)srcbits + srclinebytes;
1365 dstbits = (char*)dstbits + dstlinebytes;
1369 static void X11DRV_DIB_Convert_0888_to_565_reverse(int width, int height,
1370 const void* srcbits, int srclinebytes,
1371 void* dstbits, int dstlinebytes)
1373 const DWORD* srcpixel;
1374 WORD* dstpixel;
1375 int x,y;
1377 for (y=0; y<height; y++) {
1378 srcpixel=srcbits;
1379 dstpixel=dstbits;
1380 for (x=0; x<width; x++) {
1381 DWORD srcval;
1382 srcval=*srcpixel++;
1383 *dstpixel++=((srcval >> 19) & 0x001f) | /* h */
1384 ((srcval >> 5) & 0x07e0) | /* g */
1385 ((srcval << 8) & 0xf800); /* l */
1387 srcbits = (char*)srcbits + srclinebytes;
1388 dstbits = (char*)dstbits + dstlinebytes;
1392 static void X11DRV_DIB_Convert_any0888_to_5x5(int width, int height,
1393 const void* srcbits, int srclinebytes,
1394 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1395 void* dstbits, int dstlinebytes,
1396 WORD rdst, WORD gdst, WORD bdst)
1398 int rRightShift,gRightShift,bRightShift;
1399 int rLeftShift,gLeftShift,bLeftShift;
1400 const DWORD* srcpixel;
1401 WORD* dstpixel;
1402 int x,y;
1404 /* Here is how we proceed. Assume we have rsrc=0x0000ff00 and our pixel
1405 * contains 0x11223344.
1406 * - first we shift 0x11223344 right by rRightShift to bring the most
1407 * significant bits of the red components in the bottom 5 (or 6) bits
1408 * -> 0x4488c
1409 * - then we remove non red bits by anding with the modified rdst (0x1f)
1410 * -> 0x0c
1411 * - finally shift these bits left by rLeftShift so that they end up in
1412 * the right place
1413 * -> 0x3000
1415 rRightShift=X11DRV_DIB_MaskToShift(rsrc)+3;
1416 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1417 gRightShift+=(gdst==0x07e0?2:3);
1418 bRightShift=X11DRV_DIB_MaskToShift(bsrc)+3;
1420 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1421 rdst=rdst >> rLeftShift;
1422 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1423 gdst=gdst >> gLeftShift;
1424 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1425 bdst=bdst >> bLeftShift;
1427 for (y=0; y<height; y++) {
1428 srcpixel=srcbits;
1429 dstpixel=dstbits;
1430 for (x=0; x<width; x++) {
1431 DWORD srcval;
1432 srcval=*srcpixel++;
1433 *dstpixel++=(((srcval >> rRightShift) & rdst) << rLeftShift) |
1434 (((srcval >> gRightShift) & gdst) << gLeftShift) |
1435 (((srcval >> bRightShift) & bdst) << bLeftShift);
1437 srcbits = (char*)srcbits + srclinebytes;
1438 dstbits = (char*)dstbits + dstlinebytes;
1442 static void X11DRV_DIB_Convert_0888_to_888_asis(int width, int height,
1443 const void* srcbits, int srclinebytes,
1444 void* dstbits, int dstlinebytes)
1446 const DWORD* srcpixel;
1447 DWORD* dstpixel;
1448 BYTE* dstbyte;
1449 int x,y;
1450 int oddwidth;
1452 oddwidth=width & 3;
1453 width=width/4;
1454 for (y=0; y<height; y++) {
1455 srcpixel=srcbits;
1456 dstpixel=dstbits;
1457 for (x=0; x<width; x++) {
1458 /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */
1459 DWORD srcval;
1460 srcval=((*srcpixel++) & 0x00ffffff); /* h1, g1, l1*/
1461 *dstpixel++=srcval | ((*srcpixel) << 24); /* h2 */
1462 srcval=((*srcpixel++ >> 8 ) & 0x0000ffff); /* g2, l2 */
1463 *dstpixel++=srcval | ((*srcpixel) << 16); /* h3, g3 */
1464 srcval=((*srcpixel++ >> 16) & 0x000000ff); /* l3 */
1465 *dstpixel++=srcval | ((*srcpixel++) << 8); /* h4, g4, l4 */
1467 /* And now up to 3 odd pixels */
1468 dstbyte=(BYTE*)dstpixel;
1469 for (x=0; x<oddwidth; x++) {
1470 DWORD srcval;
1471 srcval=*srcpixel++;
1472 *((WORD*)dstbyte)++=srcval; /* h, g */
1473 *dstbyte++=srcval >> 16; /* l */
1475 srcbits = (char*)srcbits + srclinebytes;
1476 dstbits = (char*)dstbits + dstlinebytes;
1480 static void X11DRV_DIB_Convert_0888_to_888_reverse(int width, int height,
1481 const void* srcbits, int srclinebytes,
1482 void* dstbits, int dstlinebytes)
1484 const DWORD* srcpixel;
1485 DWORD* dstpixel;
1486 BYTE* dstbyte;
1487 int x,y;
1488 int oddwidth;
1490 oddwidth=width & 3;
1491 width=width/4;
1492 for (y=0; y<height; y++) {
1493 srcpixel=srcbits;
1494 dstpixel=dstbits;
1495 for (x=0; x<width; x++) {
1496 /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */
1497 DWORD srcval1,srcval2;
1498 srcval1=*srcpixel++;
1499 srcval2= ((srcval1 >> 16) & 0x000000ff) | /* h1 */
1500 ( srcval1 & 0x0000ff00) | /* g1 */
1501 ((srcval1 << 16) & 0x00ff0000); /* l1 */
1502 srcval1=*srcpixel++;
1503 *dstpixel++=srcval2 |
1504 ((srcval1 << 8) & 0xff000000); /* h2 */
1505 srcval2= ((srcval1 >> 8) & 0x000000ff) | /* g2 */
1506 ((srcval1 << 8) & 0x0000ff00); /* l2 */
1507 srcval1=*srcpixel++;
1508 *dstpixel++=srcval2 |
1509 ( srcval1 & 0x00ff0000) | /* h3 */
1510 ((srcval1 << 16) & 0xff000000); /* g3 */
1511 srcval2= ( srcval1 & 0x000000ff); /* l3 */
1512 srcval1=*srcpixel++;
1513 *dstpixel++=srcval2 |
1514 ((srcval1 >> 8) & 0x0000ff00) | /* h4 */
1515 ((srcval1 << 8) & 0x00ff0000) | /* g4 */
1516 ( srcval1 << 24); /* l4 */
1518 /* And now up to 3 odd pixels */
1519 dstbyte=(BYTE*)dstpixel;
1520 for (x=0; x<oddwidth; x++) {
1521 DWORD srcval;
1522 srcval=*srcpixel++;
1523 *((WORD*)dstbyte)++=((srcval >> 16) & 0x00ff) | /* h */
1524 (srcval & 0xff00); /* g */
1525 *dstbyte++=srcval; /* l */
1527 srcbits = (char*)srcbits + srclinebytes;
1528 dstbits = (char*)dstbits + dstlinebytes;
1532 static void X11DRV_DIB_Convert_any0888_to_rgb888(int width, int height,
1533 const void* srcbits, int srclinebytes,
1534 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1535 void* dstbits, int dstlinebytes)
1537 int rRightShift,gRightShift,bRightShift;
1538 const DWORD* srcpixel;
1539 BYTE* dstpixel;
1540 int x,y;
1542 rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1543 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1544 bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1545 for (y=0; y<height; y++) {
1546 srcpixel=srcbits;
1547 dstpixel=dstbits;
1548 for (x=0; x<width; x++) {
1549 DWORD srcval;
1550 srcval=*srcpixel++;
1551 dstpixel[0]=(srcval >> bRightShift); /* b */
1552 dstpixel[1]=(srcval >> gRightShift); /* g */
1553 dstpixel[2]=(srcval >> rRightShift); /* r */
1554 dstpixel+=3;
1556 srcbits = (char*)srcbits + srclinebytes;
1557 dstbits = (char*)dstbits + dstlinebytes;
1561 static void X11DRV_DIB_Convert_any0888_to_bgr888(int width, int height,
1562 const void* srcbits, int srclinebytes,
1563 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1564 void* dstbits, int dstlinebytes)
1566 int rRightShift,gRightShift,bRightShift;
1567 const DWORD* srcpixel;
1568 BYTE* dstpixel;
1569 int x,y;
1571 rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1572 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1573 bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1574 for (y=0; y<height; y++) {
1575 srcpixel=srcbits;
1576 dstpixel=dstbits;
1577 for (x=0; x<width; x++) {
1578 DWORD srcval;
1579 srcval=*srcpixel++;
1580 dstpixel[0]=(srcval >> rRightShift); /* r */
1581 dstpixel[1]=(srcval >> gRightShift); /* g */
1582 dstpixel[2]=(srcval >> bRightShift); /* b */
1583 dstpixel+=3;
1585 srcbits = (char*)srcbits + srclinebytes;
1586 dstbits = (char*)dstbits + dstlinebytes;
1590 /***********************************************************************
1591 * X11DRV_DIB_SetImageBits_1
1593 * SetDIBits for a 1-bit deep DIB.
1595 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
1596 DWORD srcwidth, DWORD dstwidth, int left,
1597 int *colors, XImage *bmpImage, DWORD linebytes)
1599 int h;
1600 const BYTE* srcbyte;
1601 BYTE srcval, extra;
1602 DWORD i, x;
1604 if (lines < 0 ) {
1605 lines = -lines;
1606 srcbits = srcbits + linebytes * (lines - 1);
1607 linebytes = -linebytes;
1610 if ((extra = (left & 7)) != 0) {
1611 left &= ~7;
1612 dstwidth += extra;
1614 srcbits += left >> 3;
1616 /* ==== pal 1 dib -> any bmp format ==== */
1617 for (h = lines-1; h >=0; h--) {
1618 srcbyte=srcbits;
1619 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
1620 for (i = dstwidth/8, x = left; i > 0; i--) {
1621 srcval=*srcbyte++;
1622 XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
1623 XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
1624 XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
1625 XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
1626 XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
1627 XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
1628 XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
1629 XPutPixel( bmpImage, x++, h, colors[ srcval & 1] );
1631 srcval=*srcbyte;
1632 switch (dstwidth & 7)
1634 case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1635 case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1636 case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1637 case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1638 case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1639 case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1640 case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
1642 srcbits += linebytes;
1646 /***********************************************************************
1647 * X11DRV_DIB_GetImageBits_1
1649 * GetDIBits for a 1-bit deep DIB.
1651 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
1652 DWORD dstwidth, DWORD srcwidth,
1653 RGBQUAD *colors, PALETTEENTRY *srccolors,
1654 XImage *bmpImage, DWORD linebytes )
1656 DWORD x;
1657 int h;
1659 if (lines < 0 ) {
1660 lines = -lines;
1661 dstbits = dstbits + linebytes * (lines - 1);
1662 linebytes = -linebytes;
1665 switch (bmpImage->depth)
1667 case 1:
1668 case 4:
1669 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1670 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
1671 BYTE* dstbyte;
1673 for (h=lines-1; h>=0; h--) {
1674 BYTE dstval;
1675 dstbyte=dstbits;
1676 dstval=0;
1677 for (x=0; x<dstwidth; x++) {
1678 PALETTEENTRY srcval;
1679 srcval=srccolors[XGetPixel(bmpImage, x, h)];
1680 dstval|=(X11DRV_DIB_GetNearestIndex
1681 (colors, 2,
1682 srcval.peRed,
1683 srcval.peGreen,
1684 srcval.peBlue) << (7 - (x & 7)));
1685 if ((x&7)==7) {
1686 *dstbyte++=dstval;
1687 dstval=0;
1690 if ((dstwidth&7)!=0) {
1691 *dstbyte=dstval;
1693 dstbits += linebytes;
1695 } else {
1696 goto notsupported;
1698 break;
1700 case 8:
1701 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1702 /* ==== pal 8 bmp -> pal 1 dib ==== */
1703 const void* srcbits;
1704 const BYTE* srcpixel;
1705 BYTE* dstbyte;
1707 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1709 for (h=0; h<lines; h++) {
1710 BYTE dstval;
1711 srcpixel=srcbits;
1712 dstbyte=dstbits;
1713 dstval=0;
1714 for (x=0; x<dstwidth; x++) {
1715 PALETTEENTRY srcval;
1716 srcval=srccolors[(int)*srcpixel++];
1717 dstval|=(X11DRV_DIB_GetNearestIndex
1718 (colors, 2,
1719 srcval.peRed,
1720 srcval.peGreen,
1721 srcval.peBlue) << (7-(x&7)) );
1722 if ((x&7)==7) {
1723 *dstbyte++=dstval;
1724 dstval=0;
1727 if ((dstwidth&7)!=0) {
1728 *dstbyte=dstval;
1730 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1731 dstbits += linebytes;
1733 } else {
1734 goto notsupported;
1736 break;
1738 case 15:
1739 case 16:
1741 const void* srcbits;
1742 const WORD* srcpixel;
1743 BYTE* dstbyte;
1745 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1747 if (bmpImage->green_mask==0x03e0) {
1748 if (bmpImage->red_mask==0x7c00) {
1749 /* ==== rgb 555 bmp -> pal 1 dib ==== */
1750 for (h=0; h<lines; h++) {
1751 BYTE dstval;
1752 srcpixel=srcbits;
1753 dstbyte=dstbits;
1754 dstval=0;
1755 for (x=0; x<dstwidth; x++) {
1756 WORD srcval;
1757 srcval=*srcpixel++;
1758 dstval|=(X11DRV_DIB_GetNearestIndex
1759 (colors, 2,
1760 ((srcval >> 7) & 0xf8) | /* r */
1761 ((srcval >> 12) & 0x07),
1762 ((srcval >> 2) & 0xf8) | /* g */
1763 ((srcval >> 7) & 0x07),
1764 ((srcval << 3) & 0xf8) | /* b */
1765 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
1766 if ((x&7)==7) {
1767 *dstbyte++=dstval;
1768 dstval=0;
1771 if ((dstwidth&7)!=0) {
1772 *dstbyte=dstval;
1774 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1775 dstbits += linebytes;
1777 } else if (bmpImage->blue_mask==0x7c00) {
1778 /* ==== bgr 555 bmp -> pal 1 dib ==== */
1779 for (h=0; h<lines; h++) {
1780 WORD dstval;
1781 srcpixel=srcbits;
1782 dstbyte=dstbits;
1783 dstval=0;
1784 for (x=0; x<dstwidth; x++) {
1785 BYTE srcval;
1786 srcval=*srcpixel++;
1787 dstval|=(X11DRV_DIB_GetNearestIndex
1788 (colors, 2,
1789 ((srcval << 3) & 0xf8) | /* r */
1790 ((srcval >> 2) & 0x07),
1791 ((srcval >> 2) & 0xf8) | /* g */
1792 ((srcval >> 7) & 0x07),
1793 ((srcval >> 7) & 0xf8) | /* b */
1794 ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
1795 if ((x&7)==7) {
1796 *dstbyte++=dstval;
1797 dstval=0;
1800 if ((dstwidth&7)!=0) {
1801 *dstbyte=dstval;
1803 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1804 dstbits += linebytes;
1806 } else {
1807 goto notsupported;
1809 } else if (bmpImage->green_mask==0x07e0) {
1810 if (bmpImage->red_mask==0xf800) {
1811 /* ==== rgb 565 bmp -> pal 1 dib ==== */
1812 for (h=0; h<lines; h++) {
1813 BYTE dstval;
1814 srcpixel=srcbits;
1815 dstbyte=dstbits;
1816 dstval=0;
1817 for (x=0; x<dstwidth; x++) {
1818 WORD srcval;
1819 srcval=*srcpixel++;
1820 dstval|=(X11DRV_DIB_GetNearestIndex
1821 (colors, 2,
1822 ((srcval >> 8) & 0xf8) | /* r */
1823 ((srcval >> 13) & 0x07),
1824 ((srcval >> 3) & 0xfc) | /* g */
1825 ((srcval >> 9) & 0x03),
1826 ((srcval << 3) & 0xf8) | /* b */
1827 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
1828 if ((x&7)==7) {
1829 *dstbyte++=dstval;
1830 dstval=0;
1833 if ((dstwidth&7)!=0) {
1834 *dstbyte=dstval;
1836 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1837 dstbits += linebytes;
1839 } else if (bmpImage->blue_mask==0xf800) {
1840 /* ==== bgr 565 bmp -> pal 1 dib ==== */
1841 for (h=0; h<lines; h++) {
1842 BYTE dstval;
1843 srcpixel=srcbits;
1844 dstbyte=dstbits;
1845 dstval=0;
1846 for (x=0; x<dstwidth; x++) {
1847 WORD srcval;
1848 srcval=*srcpixel++;
1849 dstval|=(X11DRV_DIB_GetNearestIndex
1850 (colors, 2,
1851 ((srcval << 3) & 0xf8) | /* r */
1852 ((srcval >> 2) & 0x07),
1853 ((srcval >> 3) & 0xfc) | /* g */
1854 ((srcval >> 9) & 0x03),
1855 ((srcval >> 8) & 0xf8) | /* b */
1856 ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
1857 if ((x&7)==7) {
1858 *dstbyte++=dstval;
1859 dstval=0;
1862 if ((dstwidth&7)!=0) {
1863 *dstbyte=dstval;
1865 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1866 dstbits += linebytes;
1868 } else {
1869 goto notsupported;
1871 } else {
1872 goto notsupported;
1875 break;
1877 case 24:
1878 case 32:
1880 const void* srcbits;
1881 const BYTE *srcbyte;
1882 BYTE* dstbyte;
1883 int bytes_per_pixel;
1885 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1886 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1888 if (bmpImage->green_mask!=0x00ff00 ||
1889 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1890 goto notsupported;
1891 } else if (bmpImage->blue_mask==0xff) {
1892 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
1893 for (h=0; h<lines; h++) {
1894 BYTE dstval;
1895 srcbyte=srcbits;
1896 dstbyte=dstbits;
1897 dstval=0;
1898 for (x=0; x<dstwidth; x++) {
1899 dstval|=(X11DRV_DIB_GetNearestIndex
1900 (colors, 2,
1901 srcbyte[2],
1902 srcbyte[1],
1903 srcbyte[0]) << (7-(x&7)) );
1904 srcbyte+=bytes_per_pixel;
1905 if ((x&7)==7) {
1906 *dstbyte++=dstval;
1907 dstval=0;
1910 if ((dstwidth&7)!=0) {
1911 *dstbyte=dstval;
1913 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1914 dstbits += linebytes;
1916 } else {
1917 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
1918 for (h=0; h<lines; h++) {
1919 BYTE dstval;
1920 srcbyte=srcbits;
1921 dstbyte=dstbits;
1922 dstval=0;
1923 for (x=0; x<dstwidth; x++) {
1924 dstval|=(X11DRV_DIB_GetNearestIndex
1925 (colors, 2,
1926 srcbyte[0],
1927 srcbyte[1],
1928 srcbyte[2]) << (7-(x&7)) );
1929 srcbyte+=bytes_per_pixel;
1930 if ((x&7)==7) {
1931 *dstbyte++=dstval;
1932 dstval=0;
1935 if ((dstwidth&7)!=0) {
1936 *dstbyte=dstval;
1938 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1939 dstbits += linebytes;
1943 break;
1945 default:
1946 notsupported:
1948 BYTE* dstbyte;
1949 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
1951 /* ==== any bmp format -> pal 1 dib ==== */
1952 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
1953 bmpImage->bits_per_pixel, bmpImage->red_mask,
1954 bmpImage->green_mask, bmpImage->blue_mask );
1956 for (h=lines-1; h>=0; h--) {
1957 BYTE dstval;
1958 dstbyte=dstbits;
1959 dstval=0;
1960 for (x=0; x<dstwidth; x++) {
1961 dstval|=(XGetPixel( bmpImage, x, h) >= white) << (7 - (x&7));
1962 if ((x&7)==7) {
1963 *dstbyte++=dstval;
1964 dstval=0;
1967 if ((dstwidth&7)!=0) {
1968 *dstbyte=dstval;
1970 dstbits += linebytes;
1973 break;
1977 /***********************************************************************
1978 * X11DRV_DIB_SetImageBits_4
1980 * SetDIBits for a 4-bit deep DIB.
1982 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
1983 DWORD srcwidth, DWORD dstwidth, int left,
1984 int *colors, XImage *bmpImage, DWORD linebytes)
1986 int h;
1987 const BYTE* srcbyte;
1988 DWORD i, x;
1990 if (lines < 0 ) {
1991 lines = -lines;
1992 srcbits = srcbits + linebytes * (lines - 1);
1993 linebytes = -linebytes;
1996 if (left & 1) {
1997 left--;
1998 dstwidth++;
2000 srcbits += left >> 1;
2002 /* ==== pal 4 dib -> any bmp format ==== */
2003 for (h = lines-1; h >= 0; h--) {
2004 srcbyte=srcbits;
2005 for (i = dstwidth/2, x = left; i > 0; i--) {
2006 BYTE srcval=*srcbyte++;
2007 XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
2008 XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
2010 if (dstwidth & 1)
2011 XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
2012 srcbits += linebytes;
2018 /***********************************************************************
2019 * X11DRV_DIB_GetImageBits_4
2021 * GetDIBits for a 4-bit deep DIB.
2023 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
2024 DWORD srcwidth, DWORD dstwidth,
2025 RGBQUAD *colors, PALETTEENTRY *srccolors,
2026 XImage *bmpImage, DWORD linebytes )
2028 DWORD x;
2029 int h;
2030 BYTE *bits;
2032 if (lines < 0 )
2034 lines = -lines;
2035 dstbits = dstbits + ( linebytes * (lines-1) );
2036 linebytes = -linebytes;
2039 bits = dstbits;
2041 switch (bmpImage->depth) {
2042 case 1:
2043 case 4:
2044 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2045 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
2046 BYTE* dstbyte;
2048 for (h = lines-1; h >= 0; h--) {
2049 BYTE dstval;
2050 dstbyte=dstbits;
2051 dstval=0;
2052 for (x = 0; x < dstwidth; x++) {
2053 PALETTEENTRY srcval;
2054 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2055 dstval|=(X11DRV_DIB_GetNearestIndex
2056 (colors, 16,
2057 srcval.peRed,
2058 srcval.peGreen,
2059 srcval.peBlue) << (4-((x&1)<<2)));
2060 if ((x&1)==1) {
2061 *dstbyte++=dstval;
2062 dstval=0;
2065 if ((dstwidth&1)!=0) {
2066 *dstbyte=dstval;
2068 dstbits += linebytes;
2070 } else {
2071 goto notsupported;
2073 break;
2075 case 8:
2076 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2077 /* ==== pal 8 bmp -> pal 4 dib ==== */
2078 const void* srcbits;
2079 const BYTE *srcpixel;
2080 BYTE* dstbyte;
2082 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2083 for (h=0; h<lines; h++) {
2084 BYTE dstval;
2085 srcpixel=srcbits;
2086 dstbyte=dstbits;
2087 dstval=0;
2088 for (x=0; x<dstwidth; x++) {
2089 PALETTEENTRY srcval;
2090 srcval = srccolors[(int)*srcpixel++];
2091 dstval|=(X11DRV_DIB_GetNearestIndex
2092 (colors, 16,
2093 srcval.peRed,
2094 srcval.peGreen,
2095 srcval.peBlue) << (4*(1-(x&1))) );
2096 if ((x&1)==1) {
2097 *dstbyte++=dstval;
2098 dstval=0;
2101 if ((dstwidth&1)!=0) {
2102 *dstbyte=dstval;
2104 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2105 dstbits += linebytes;
2107 } else {
2108 goto notsupported;
2110 break;
2112 case 15:
2113 case 16:
2115 const void* srcbits;
2116 const WORD* srcpixel;
2117 BYTE* dstbyte;
2119 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2121 if (bmpImage->green_mask==0x03e0) {
2122 if (bmpImage->red_mask==0x7c00) {
2123 /* ==== rgb 555 bmp -> pal 4 dib ==== */
2124 for (h=0; h<lines; h++) {
2125 BYTE dstval;
2126 srcpixel=srcbits;
2127 dstbyte=dstbits;
2128 dstval=0;
2129 for (x=0; x<dstwidth; x++) {
2130 WORD srcval;
2131 srcval=*srcpixel++;
2132 dstval|=(X11DRV_DIB_GetNearestIndex
2133 (colors, 16,
2134 ((srcval >> 7) & 0xf8) | /* r */
2135 ((srcval >> 12) & 0x07),
2136 ((srcval >> 2) & 0xf8) | /* g */
2137 ((srcval >> 7) & 0x07),
2138 ((srcval << 3) & 0xf8) | /* b */
2139 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
2140 if ((x&1)==1) {
2141 *dstbyte++=dstval;
2142 dstval=0;
2145 if ((dstwidth&1)!=0) {
2146 *dstbyte=dstval;
2148 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2149 dstbits += linebytes;
2151 } else if (bmpImage->blue_mask==0x7c00) {
2152 /* ==== bgr 555 bmp -> pal 4 dib ==== */
2153 for (h=0; h<lines; h++) {
2154 WORD dstval;
2155 srcpixel=srcbits;
2156 dstbyte=dstbits;
2157 dstval=0;
2158 for (x=0; x<dstwidth; x++) {
2159 WORD srcval;
2160 srcval=*srcpixel++;
2161 dstval|=(X11DRV_DIB_GetNearestIndex
2162 (colors, 16,
2163 ((srcval << 3) & 0xf8) | /* r */
2164 ((srcval >> 2) & 0x07),
2165 ((srcval >> 2) & 0xf8) | /* g */
2166 ((srcval >> 7) & 0x07),
2167 ((srcval >> 7) & 0xf8) | /* b */
2168 ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
2169 if ((x&1)==1) {
2170 *dstbyte++=dstval;
2171 dstval=0;
2174 if ((dstwidth&1)!=0) {
2175 *dstbyte=dstval;
2177 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2178 dstbits += linebytes;
2180 } else {
2181 goto notsupported;
2183 } else if (bmpImage->green_mask==0x07e0) {
2184 if (bmpImage->red_mask==0xf800) {
2185 /* ==== rgb 565 bmp -> pal 4 dib ==== */
2186 for (h=0; h<lines; h++) {
2187 BYTE dstval;
2188 srcpixel=srcbits;
2189 dstbyte=dstbits;
2190 dstval=0;
2191 for (x=0; x<dstwidth; x++) {
2192 WORD srcval;
2193 srcval=*srcpixel++;
2194 dstval|=(X11DRV_DIB_GetNearestIndex
2195 (colors, 16,
2196 ((srcval >> 8) & 0xf8) | /* r */
2197 ((srcval >> 13) & 0x07),
2198 ((srcval >> 3) & 0xfc) | /* g */
2199 ((srcval >> 9) & 0x03),
2200 ((srcval << 3) & 0xf8) | /* b */
2201 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
2202 if ((x&1)==1) {
2203 *dstbyte++=dstval;
2204 dstval=0;
2207 if ((dstwidth&1)!=0) {
2208 *dstbyte=dstval;
2210 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2211 dstbits += linebytes;
2213 } else if (bmpImage->blue_mask==0xf800) {
2214 /* ==== bgr 565 bmp -> pal 4 dib ==== */
2215 for (h=0; h<lines; h++) {
2216 WORD dstval;
2217 srcpixel=srcbits;
2218 dstbyte=dstbits;
2219 dstval=0;
2220 for (x=0; x<dstwidth; x++) {
2221 WORD srcval;
2222 srcval=*srcpixel++;
2223 dstval|=(X11DRV_DIB_GetNearestIndex
2224 (colors, 16,
2225 ((srcval << 3) & 0xf8) | /* r */
2226 ((srcval >> 2) & 0x07),
2227 ((srcval >> 3) & 0xfc) | /* g */
2228 ((srcval >> 9) & 0x03),
2229 ((srcval >> 8) & 0xf8) | /* b */
2230 ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
2231 if ((x&1)==1) {
2232 *dstbyte++=dstval;
2233 dstval=0;
2236 if ((dstwidth&1)!=0) {
2237 *dstbyte=dstval;
2239 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2240 dstbits += linebytes;
2242 } else {
2243 goto notsupported;
2245 } else {
2246 goto notsupported;
2249 break;
2251 case 24:
2252 if (bmpImage->bits_per_pixel==24) {
2253 const void* srcbits;
2254 const BYTE *srcbyte;
2255 BYTE* dstbyte;
2257 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2259 if (bmpImage->green_mask!=0x00ff00 ||
2260 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2261 goto notsupported;
2262 } else if (bmpImage->blue_mask==0xff) {
2263 /* ==== rgb 888 bmp -> pal 4 dib ==== */
2264 for (h=0; h<lines; h++) {
2265 srcbyte=srcbits;
2266 dstbyte=dstbits;
2267 for (x=0; x<dstwidth/2; x++) {
2268 /* Do 2 pixels at a time */
2269 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2270 (colors, 16,
2271 srcbyte[2],
2272 srcbyte[1],
2273 srcbyte[0]) << 4) |
2274 X11DRV_DIB_GetNearestIndex
2275 (colors, 16,
2276 srcbyte[5],
2277 srcbyte[4],
2278 srcbyte[3]);
2279 srcbyte+=6;
2281 if (dstwidth&1) {
2282 /* And the the odd pixel */
2283 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2284 (colors, 16,
2285 srcbyte[2],
2286 srcbyte[1],
2287 srcbyte[0]) << 4);
2289 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2290 dstbits += linebytes;
2292 } else {
2293 /* ==== bgr 888 bmp -> pal 4 dib ==== */
2294 for (h=0; h<lines; h++) {
2295 srcbyte=srcbits;
2296 dstbyte=dstbits;
2297 for (x=0; x<dstwidth/2; x++) {
2298 /* Do 2 pixels at a time */
2299 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2300 (colors, 16,
2301 srcbyte[0],
2302 srcbyte[1],
2303 srcbyte[2]) << 4) |
2304 X11DRV_DIB_GetNearestIndex
2305 (colors, 16,
2306 srcbyte[3],
2307 srcbyte[4],
2308 srcbyte[5]);
2309 srcbyte+=6;
2311 if (dstwidth&1) {
2312 /* And the the odd pixel */
2313 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2314 (colors, 16,
2315 srcbyte[0],
2316 srcbyte[1],
2317 srcbyte[2]) << 4);
2319 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2320 dstbits += linebytes;
2323 break;
2325 /* Fall through */
2327 case 32:
2329 const void* srcbits;
2330 const BYTE *srcbyte;
2331 BYTE* dstbyte;
2333 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2335 if (bmpImage->green_mask!=0x00ff00 ||
2336 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2337 goto notsupported;
2338 } else if (bmpImage->blue_mask==0xff) {
2339 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
2340 for (h=0; h<lines; h++) {
2341 srcbyte=srcbits;
2342 dstbyte=dstbits;
2343 for (x=0; x<dstwidth/2; x++) {
2344 /* Do 2 pixels at a time */
2345 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2346 (colors, 16,
2347 srcbyte[2],
2348 srcbyte[1],
2349 srcbyte[0]) << 4) |
2350 X11DRV_DIB_GetNearestIndex
2351 (colors, 16,
2352 srcbyte[6],
2353 srcbyte[5],
2354 srcbyte[4]);
2355 srcbyte+=8;
2357 if (dstwidth&1) {
2358 /* And the the odd pixel */
2359 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2360 (colors, 16,
2361 srcbyte[2],
2362 srcbyte[1],
2363 srcbyte[0]) << 4);
2365 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2366 dstbits += linebytes;
2368 } else {
2369 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
2370 for (h=0; h<lines; h++) {
2371 srcbyte=srcbits;
2372 dstbyte=dstbits;
2373 for (x=0; x<dstwidth/2; x++) {
2374 /* Do 2 pixels at a time */
2375 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2376 (colors, 16,
2377 srcbyte[0],
2378 srcbyte[1],
2379 srcbyte[2]) << 4) |
2380 X11DRV_DIB_GetNearestIndex
2381 (colors, 16,
2382 srcbyte[4],
2383 srcbyte[5],
2384 srcbyte[6]);
2385 srcbyte+=8;
2387 if (dstwidth&1) {
2388 /* And the the odd pixel */
2389 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2390 (colors, 16,
2391 srcbyte[0],
2392 srcbyte[1],
2393 srcbyte[2]) << 4);
2395 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2396 dstbits += linebytes;
2400 break;
2402 default:
2403 notsupported:
2405 BYTE* dstbyte;
2407 /* ==== any bmp format -> pal 4 dib ==== */
2408 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
2409 bmpImage->bits_per_pixel, bmpImage->red_mask,
2410 bmpImage->green_mask, bmpImage->blue_mask );
2411 for (h=lines-1; h>=0; h--) {
2412 dstbyte=dstbits;
2413 for (x=0; x<(dstwidth & ~1); x+=2) {
2414 *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
2415 X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
2417 if (dstwidth & 1) {
2418 *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
2420 dstbits += linebytes;
2423 break;
2427 /***********************************************************************
2428 * X11DRV_DIB_SetImageBits_RLE4
2430 * SetDIBits for a 4-bit deep compressed DIB.
2432 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
2433 DWORD width, DWORD dstwidth,
2434 int left, int *colors,
2435 XImage *bmpImage )
2437 int x = 0, y = lines - 1, c, length;
2438 const BYTE *begin = bits;
2440 while (y >= 0)
2442 length = *bits++;
2443 if (length) { /* encoded */
2444 c = *bits++;
2445 while (length--) {
2446 if (x >= width) break;
2447 XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2448 if (!length--) break;
2449 if (x >= width) break;
2450 XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2452 } else {
2453 length = *bits++;
2454 switch (length)
2456 case RLE_EOL:
2457 x = 0;
2458 y--;
2459 break;
2461 case RLE_END:
2462 return;
2464 case RLE_DELTA:
2465 x += *bits++;
2466 y -= *bits++;
2467 break;
2469 default: /* absolute */
2470 while (length--) {
2471 c = *bits++;
2472 if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2473 if (!length--) break;
2474 if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2476 if ((bits - begin) & 1)
2477 bits++;
2485 /***********************************************************************
2486 * X11DRV_DIB_SetImageBits_8
2488 * SetDIBits for an 8-bit deep DIB.
2490 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
2491 DWORD srcwidth, DWORD dstwidth, int left,
2492 const int *colors, XImage *bmpImage,
2493 DWORD linebytes )
2495 DWORD x;
2496 int h;
2497 const BYTE* srcbyte;
2498 BYTE* dstbits;
2500 if (lines < 0 )
2502 lines = -lines;
2503 srcbits = srcbits + linebytes * (lines-1);
2504 linebytes = -linebytes;
2506 srcbits += left;
2507 srcbyte = srcbits;
2509 switch (bmpImage->depth) {
2510 case 15:
2511 case 16:
2512 #if defined(__i386__) && defined(__GNUC__)
2513 /* Some X servers might have 32 bit/ 16bit deep pixel */
2514 if (lines && dstwidth && (bmpImage->bits_per_pixel == 16) &&
2515 (ImageByteOrder(gdi_display)==LSBFirst) )
2517 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2518 /* FIXME: Does this really handle all these cases correctly? */
2519 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
2520 for (h = lines ; h--; ) {
2521 int _cl1,_cl2; /* temp outputs for asm below */
2522 /* Borrowed from DirectDraw */
2523 __asm__ __volatile__(
2524 "xor %%eax,%%eax\n"
2525 "cld\n"
2526 "1:\n"
2527 " lodsb\n"
2528 " movw (%%edx,%%eax,4),%%ax\n"
2529 " stosw\n"
2530 " xor %%eax,%%eax\n"
2531 " loop 1b\n"
2532 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2533 :"S" (srcbyte),
2534 "D" (dstbits),
2535 "c" (dstwidth),
2536 "d" (colors)
2537 :"eax", "cc", "memory"
2539 srcbyte = (srcbits += linebytes);
2540 dstbits -= bmpImage->bytes_per_line;
2542 return;
2544 break;
2545 #endif
2546 case 24:
2547 case 32:
2548 #if defined(__i386__) && defined(__GNUC__)
2549 if (lines && dstwidth && (bmpImage->bits_per_pixel == 32) &&
2550 (ImageByteOrder(gdi_display)==LSBFirst) )
2552 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2553 /* FIXME: Does this really handle both cases correctly? */
2554 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
2555 for (h = lines ; h--; ) {
2556 int _cl1,_cl2; /* temp outputs for asm below */
2557 /* Borrowed from DirectDraw */
2558 __asm__ __volatile__(
2559 "xor %%eax,%%eax\n"
2560 "cld\n"
2561 "1:\n"
2562 " lodsb\n"
2563 " movl (%%edx,%%eax,4),%%eax\n"
2564 " stosl\n"
2565 " xor %%eax,%%eax\n"
2566 " loop 1b\n"
2567 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2568 :"S" (srcbyte),
2569 "D" (dstbits),
2570 "c" (dstwidth),
2571 "d" (colors)
2572 :"eax", "cc", "memory"
2574 srcbyte = (srcbits += linebytes);
2575 dstbits -= bmpImage->bytes_per_line;
2577 return;
2579 break;
2580 #endif
2581 default:
2582 break; /* use slow generic case below */
2585 /* ==== pal 8 dib -> any bmp format ==== */
2586 for (h=lines-1; h>=0; h--) {
2587 for (x=left; x<dstwidth+left; x++) {
2588 XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
2590 srcbyte = (srcbits += linebytes);
2594 /***********************************************************************
2595 * X11DRV_DIB_GetImageBits_8
2597 * GetDIBits for an 8-bit deep DIB.
2599 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
2600 DWORD srcwidth, DWORD dstwidth,
2601 RGBQUAD *colors, PALETTEENTRY *srccolors,
2602 XImage *bmpImage, DWORD linebytes )
2604 DWORD x;
2605 int h;
2606 BYTE* dstbyte;
2608 if (lines < 0 )
2610 lines = -lines;
2611 dstbits = dstbits + ( linebytes * (lines-1) );
2612 linebytes = -linebytes;
2616 * Hack for now
2617 * This condition is true when GetImageBits has been called by
2618 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
2619 * 256 colormaps, so we'll just use for for GetDIBits calls.
2620 * (In somes cases, in a updateDIBSection, the returned colors are bad too)
2622 if (!srccolors) goto updatesection;
2624 switch (bmpImage->depth) {
2625 case 1:
2626 case 4:
2627 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2629 /* ==== pal 1 bmp -> pal 8 dib ==== */
2630 /* ==== pal 4 bmp -> pal 8 dib ==== */
2631 for (h=lines-1; h>=0; h--) {
2632 dstbyte=dstbits;
2633 for (x=0; x<dstwidth; x++) {
2634 PALETTEENTRY srcval;
2635 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2636 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2637 srcval.peRed,
2638 srcval.peGreen,
2639 srcval.peBlue);
2641 dstbits += linebytes;
2643 } else {
2644 goto notsupported;
2646 break;
2648 case 8:
2649 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2650 /* ==== pal 8 bmp -> pal 8 dib ==== */
2651 const void* srcbits;
2652 const BYTE* srcpixel;
2654 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2655 for (h=0; h<lines; h++) {
2656 srcpixel=srcbits;
2657 dstbyte=dstbits;
2658 for (x = 0; x < dstwidth; x++) {
2659 PALETTEENTRY srcval;
2660 srcval=srccolors[(int)*srcpixel++];
2661 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2662 srcval.peRed,
2663 srcval.peGreen,
2664 srcval.peBlue);
2666 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2667 dstbits += linebytes;
2669 } else {
2670 goto notsupported;
2672 break;
2674 case 15:
2675 case 16:
2677 const void* srcbits;
2678 const WORD* srcpixel;
2679 BYTE* dstbyte;
2681 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2683 if (bmpImage->green_mask==0x03e0) {
2684 if (bmpImage->red_mask==0x7c00) {
2685 /* ==== rgb 555 bmp -> pal 8 dib ==== */
2686 for (h=0; h<lines; h++) {
2687 srcpixel=srcbits;
2688 dstbyte=dstbits;
2689 for (x=0; x<dstwidth; x++) {
2690 WORD srcval;
2691 srcval=*srcpixel++;
2692 *dstbyte++=X11DRV_DIB_GetNearestIndex
2693 (colors, 256,
2694 ((srcval >> 7) & 0xf8) | /* r */
2695 ((srcval >> 12) & 0x07),
2696 ((srcval >> 2) & 0xf8) | /* g */
2697 ((srcval >> 7) & 0x07),
2698 ((srcval << 3) & 0xf8) | /* b */
2699 ((srcval >> 2) & 0x07) );
2701 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2702 dstbits += linebytes;
2704 } else if (bmpImage->blue_mask==0x7c00) {
2705 /* ==== bgr 555 bmp -> pal 8 dib ==== */
2706 for (h=0; h<lines; h++) {
2707 srcpixel=srcbits;
2708 dstbyte=dstbits;
2709 for (x=0; x<dstwidth; x++) {
2710 WORD srcval;
2711 srcval=*srcpixel++;
2712 *dstbyte++=X11DRV_DIB_GetNearestIndex
2713 (colors, 256,
2714 ((srcval << 3) & 0xf8) | /* r */
2715 ((srcval >> 2) & 0x07),
2716 ((srcval >> 2) & 0xf8) | /* g */
2717 ((srcval >> 7) & 0x07),
2718 ((srcval >> 7) & 0xf8) | /* b */
2719 ((srcval >> 12) & 0x07) );
2721 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2722 dstbits += linebytes;
2724 } else {
2725 goto notsupported;
2727 } else if (bmpImage->green_mask==0x07e0) {
2728 if (bmpImage->red_mask==0xf800) {
2729 /* ==== rgb 565 bmp -> pal 8 dib ==== */
2730 for (h=0; h<lines; h++) {
2731 srcpixel=srcbits;
2732 dstbyte=dstbits;
2733 for (x=0; x<dstwidth; x++) {
2734 WORD srcval;
2735 srcval=*srcpixel++;
2736 *dstbyte++=X11DRV_DIB_GetNearestIndex
2737 (colors, 256,
2738 ((srcval >> 8) & 0xf8) | /* r */
2739 ((srcval >> 13) & 0x07),
2740 ((srcval >> 3) & 0xfc) | /* g */
2741 ((srcval >> 9) & 0x03),
2742 ((srcval << 3) & 0xf8) | /* b */
2743 ((srcval >> 2) & 0x07) );
2745 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2746 dstbits += linebytes;
2748 } else if (bmpImage->blue_mask==0xf800) {
2749 /* ==== bgr 565 bmp -> pal 8 dib ==== */
2750 for (h=0; h<lines; h++) {
2751 srcpixel=srcbits;
2752 dstbyte=dstbits;
2753 for (x=0; x<dstwidth; x++) {
2754 WORD srcval;
2755 srcval=*srcpixel++;
2756 *dstbyte++=X11DRV_DIB_GetNearestIndex
2757 (colors, 256,
2758 ((srcval << 3) & 0xf8) | /* r */
2759 ((srcval >> 2) & 0x07),
2760 ((srcval >> 3) & 0xfc) | /* g */
2761 ((srcval >> 9) & 0x03),
2762 ((srcval >> 8) & 0xf8) | /* b */
2763 ((srcval >> 13) & 0x07) );
2765 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2766 dstbits += linebytes;
2768 } else {
2769 goto notsupported;
2771 } else {
2772 goto notsupported;
2775 break;
2777 case 24:
2778 case 32:
2780 const void* srcbits;
2781 const BYTE *srcbyte;
2782 BYTE* dstbyte;
2783 int bytes_per_pixel;
2785 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2786 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
2788 if (bmpImage->green_mask!=0x00ff00 ||
2789 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2790 goto notsupported;
2791 } else if (bmpImage->blue_mask==0xff) {
2792 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
2793 for (h=0; h<lines; h++) {
2794 srcbyte=srcbits;
2795 dstbyte=dstbits;
2796 for (x=0; x<dstwidth; x++) {
2797 *dstbyte++=X11DRV_DIB_GetNearestIndex
2798 (colors, 256,
2799 srcbyte[2],
2800 srcbyte[1],
2801 srcbyte[0]);
2802 srcbyte+=bytes_per_pixel;
2804 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2805 dstbits += linebytes;
2807 } else {
2808 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
2809 for (h=0; h<lines; h++) {
2810 srcbyte=srcbits;
2811 dstbyte=dstbits;
2812 for (x=0; x<dstwidth; x++) {
2813 *dstbyte++=X11DRV_DIB_GetNearestIndex
2814 (colors, 256,
2815 srcbyte[0],
2816 srcbyte[1],
2817 srcbyte[2]);
2818 srcbyte+=bytes_per_pixel;
2820 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2821 dstbits += linebytes;
2825 break;
2827 default:
2828 notsupported:
2829 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
2830 bmpImage->depth, bmpImage->red_mask,
2831 bmpImage->green_mask, bmpImage->blue_mask );
2832 updatesection:
2833 /* ==== any bmp format -> pal 8 dib ==== */
2834 for (h=lines-1; h>=0; h--) {
2835 dstbyte=dstbits;
2836 for (x=0; x<dstwidth; x++) {
2837 *dstbyte=X11DRV_DIB_MapColor
2838 ((int*)colors, 256,
2839 XGetPixel(bmpImage, x, h), *dstbyte);
2840 dstbyte++;
2842 dstbits += linebytes;
2844 break;
2848 /***********************************************************************
2849 * X11DRV_DIB_SetImageBits_RLE8
2851 * SetDIBits for an 8-bit deep compressed DIB.
2853 * This function rewritten 941113 by James Youngman. WINE blew out when I
2854 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
2856 * This was because the algorithm assumed that all RLE8 bitmaps end with the
2857 * 'End of bitmap' escape code. This code is very much laxer in what it
2858 * allows to end the expansion. Possibly too lax. See the note by
2859 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
2860 * bitmap should end with RleEnd, but on the other hand, software exists
2861 * that produces ones that don't and Windows 3.1 doesn't complain a bit
2862 * about it.
2864 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
2865 * James A. Youngman <mbcstjy@afs.man.ac.uk>
2866 * [JAY]
2868 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
2869 DWORD width, DWORD dstwidth,
2870 int left, int *colors,
2871 XImage *bmpImage )
2873 int x; /* X-positon on each line. Increases. */
2874 int y; /* Line #. Starts at lines-1, decreases */
2875 const BYTE *pIn = bits; /* Pointer to current position in bits */
2876 BYTE length; /* The length pf a run */
2877 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
2880 * Note that the bitmap data is stored by Windows starting at the
2881 * bottom line of the bitmap and going upwards. Within each line,
2882 * the data is stored left-to-right. That's the reason why line
2883 * goes from lines-1 to 0. [JAY]
2886 x = 0;
2887 y = lines - 1;
2888 while (y >= 0)
2890 length = *pIn++;
2893 * If the length byte is not zero (which is the escape value),
2894 * We have a run of length pixels all the same colour. The colour
2895 * index is stored next.
2897 * If the length byte is zero, we need to read the next byte to
2898 * know what to do. [JAY]
2900 if (length != 0)
2903 * [Run-Length] Encoded mode
2905 int color = colors[*pIn++];
2906 while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
2908 else
2911 * Escape codes (may be an absolute sequence though)
2913 escape_code = (*pIn++);
2914 switch(escape_code)
2916 case RLE_EOL:
2917 x = 0;
2918 y--;
2919 break;
2921 case RLE_END:
2922 /* Not all RLE8 bitmaps end with this code. For
2923 * example, Paint Shop Pro produces some that don't.
2924 * That's (I think) what caused the previous
2925 * implementation to fail. [JAY]
2927 return;
2929 case RLE_DELTA:
2930 x += (*pIn++);
2931 y -= (*pIn++);
2932 break;
2934 default: /* switch to absolute mode */
2935 length = escape_code;
2936 while (length--)
2938 int color = colors[*pIn++];
2939 if (x >= dstwidth)
2941 pIn += length;
2942 break;
2944 XPutPixel(bmpImage, x++, y, color);
2947 * If you think for a moment you'll realise that the
2948 * only time we could ever possibly read an odd
2949 * number of bytes is when there is a 0x00 (escape),
2950 * a value >0x02 (absolute mode) and then an odd-
2951 * length run. Therefore this is the only place we
2952 * need to worry about it. Everywhere else the
2953 * bytes are always read in pairs. [JAY]
2955 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
2956 break;
2957 } /* switch (escape_code) : Escape sequence */
2963 /***********************************************************************
2964 * X11DRV_DIB_SetImageBits_16
2966 * SetDIBits for a 16-bit deep DIB.
2968 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
2969 DWORD srcwidth, DWORD dstwidth, int left,
2970 X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
2971 XImage *bmpImage, DWORD linebytes )
2973 DWORD x;
2974 int h;
2976 if (lines < 0 )
2978 lines = -lines;
2979 srcbits = srcbits + ( linebytes * (lines-1));
2980 linebytes = -linebytes;
2983 switch (bmpImage->depth)
2985 case 15:
2986 case 16:
2988 char* dstbits;
2990 srcbits=srcbits+left*2;
2991 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2993 if (bmpImage->green_mask==0x03e0) {
2994 if (gSrc==bmpImage->green_mask) {
2995 if (rSrc==bmpImage->red_mask) {
2996 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
2997 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
2998 X11DRV_DIB_Convert_any_asis
2999 (dstwidth,lines,2,
3000 srcbits,linebytes,
3001 dstbits,-bmpImage->bytes_per_line);
3002 } else if (rSrc==bmpImage->blue_mask) {
3003 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
3004 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
3005 X11DRV_DIB_Convert_555_reverse
3006 (dstwidth,lines,
3007 srcbits,linebytes,
3008 dstbits,-bmpImage->bytes_per_line);
3010 } else {
3011 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
3012 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
3013 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
3014 X11DRV_DIB_Convert_565_to_555_asis
3015 (dstwidth,lines,
3016 srcbits,linebytes,
3017 dstbits,-bmpImage->bytes_per_line);
3018 } else {
3019 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
3020 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
3021 X11DRV_DIB_Convert_565_to_555_reverse
3022 (dstwidth,lines,
3023 srcbits,linebytes,
3024 dstbits,-bmpImage->bytes_per_line);
3027 } else if (bmpImage->green_mask==0x07e0) {
3028 if (gSrc==bmpImage->green_mask) {
3029 if (rSrc==bmpImage->red_mask) {
3030 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
3031 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
3032 X11DRV_DIB_Convert_any_asis
3033 (dstwidth,lines,2,
3034 srcbits,linebytes,
3035 dstbits,-bmpImage->bytes_per_line);
3036 } else {
3037 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
3038 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
3039 X11DRV_DIB_Convert_565_reverse
3040 (dstwidth,lines,
3041 srcbits,linebytes,
3042 dstbits,-bmpImage->bytes_per_line);
3044 } else {
3045 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
3046 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
3047 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
3048 X11DRV_DIB_Convert_555_to_565_asis
3049 (dstwidth,lines,
3050 srcbits,linebytes,
3051 dstbits,-bmpImage->bytes_per_line);
3052 } else {
3053 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
3054 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
3055 X11DRV_DIB_Convert_555_to_565_reverse
3056 (dstwidth,lines,
3057 srcbits,linebytes,
3058 dstbits,-bmpImage->bytes_per_line);
3061 } else {
3062 goto notsupported;
3065 break;
3067 case 24:
3068 if (bmpImage->bits_per_pixel==24) {
3069 char* dstbits;
3071 srcbits=srcbits+left*2;
3072 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3074 if (bmpImage->green_mask!=0x00ff00 ||
3075 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3076 goto notsupported;
3077 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3078 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3079 if (gSrc==0x03e0) {
3080 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
3081 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
3082 X11DRV_DIB_Convert_555_to_888_asis
3083 (dstwidth,lines,
3084 srcbits,linebytes,
3085 dstbits,-bmpImage->bytes_per_line);
3086 } else {
3087 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
3088 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
3089 X11DRV_DIB_Convert_565_to_888_asis
3090 (dstwidth,lines,
3091 srcbits,linebytes,
3092 dstbits,-bmpImage->bytes_per_line);
3094 } else {
3095 if (gSrc==0x03e0) {
3096 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
3097 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
3098 X11DRV_DIB_Convert_555_to_888_reverse
3099 (dstwidth,lines,
3100 srcbits,linebytes,
3101 dstbits,-bmpImage->bytes_per_line);
3102 } else {
3103 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
3104 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
3105 X11DRV_DIB_Convert_565_to_888_reverse
3106 (dstwidth,lines,
3107 srcbits,linebytes,
3108 dstbits,-bmpImage->bytes_per_line);
3111 break;
3113 /* Fall through */
3115 case 32:
3117 char* dstbits;
3119 srcbits=srcbits+left*2;
3120 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3122 if (bmpImage->green_mask!=0x00ff00 ||
3123 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3124 goto notsupported;
3125 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3126 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3127 if (gSrc==0x03e0) {
3128 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
3129 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
3130 X11DRV_DIB_Convert_555_to_0888_asis
3131 (dstwidth,lines,
3132 srcbits,linebytes,
3133 dstbits,-bmpImage->bytes_per_line);
3134 } else {
3135 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
3136 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
3137 X11DRV_DIB_Convert_565_to_0888_asis
3138 (dstwidth,lines,
3139 srcbits,linebytes,
3140 dstbits,-bmpImage->bytes_per_line);
3142 } else {
3143 if (gSrc==0x03e0) {
3144 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
3145 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
3146 X11DRV_DIB_Convert_555_to_0888_reverse
3147 (dstwidth,lines,
3148 srcbits,linebytes,
3149 dstbits,-bmpImage->bytes_per_line);
3150 } else {
3151 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
3152 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
3153 X11DRV_DIB_Convert_565_to_0888_reverse
3154 (dstwidth,lines,
3155 srcbits,linebytes,
3156 dstbits,-bmpImage->bytes_per_line);
3160 break;
3162 default:
3163 notsupported:
3164 WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3165 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3166 bmpImage->green_mask, bmpImage->blue_mask );
3167 /* fall through */
3168 case 1:
3169 case 4:
3170 case 8:
3172 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
3173 const WORD* srcpixel;
3174 int rShift1,gShift1,bShift1;
3175 int rShift2,gShift2,bShift2;
3176 BYTE gMask1,gMask2;
3178 /* Set color scaling values */
3179 rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
3180 gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
3181 bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
3182 rShift2=rShift1+5;
3183 gShift2=gShift1+5;
3184 bShift2=bShift1+5;
3185 if (gSrc==0x03e0) {
3186 /* Green has 5 bits, like the others */
3187 gMask1=0xf8;
3188 gMask2=0x07;
3189 } else {
3190 /* Green has 6 bits, not 5. Compensate. */
3191 gShift1++;
3192 gShift2+=2;
3193 gMask1=0xfc;
3194 gMask2=0x03;
3197 srcbits+=2*left;
3199 /* We could split it into four separate cases to optimize
3200 * but it is probably not worth it.
3202 for (h=lines-1; h>=0; h--) {
3203 srcpixel=(const WORD*)srcbits;
3204 for (x=left; x<dstwidth+left; x++) {
3205 DWORD srcval;
3206 BYTE red,green,blue;
3207 srcval=*srcpixel++ << 16;
3208 red= ((srcval >> rShift1) & 0xf8) |
3209 ((srcval >> rShift2) & 0x07);
3210 green=((srcval >> gShift1) & gMask1) |
3211 ((srcval >> gShift2) & gMask2);
3212 blue= ((srcval >> bShift1) & 0xf8) |
3213 ((srcval >> bShift2) & 0x07);
3214 XPutPixel(bmpImage, x, h,
3215 X11DRV_PALETTE_ToPhysical
3216 (physDev, RGB(red,green,blue)));
3218 srcbits += linebytes;
3221 break;
3226 /***********************************************************************
3227 * X11DRV_DIB_GetImageBits_16
3229 * GetDIBits for an 16-bit deep DIB.
3231 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
3232 DWORD dstwidth, DWORD srcwidth,
3233 PALETTEENTRY *srccolors,
3234 DWORD rDst, DWORD gDst, DWORD bDst,
3235 XImage *bmpImage, DWORD dibpitch )
3237 DWORD x;
3238 int h;
3240 DWORD linebytes = dibpitch;
3242 if (lines < 0 )
3244 lines = -lines;
3245 dstbits = dstbits + ( linebytes * (lines-1));
3246 linebytes = -linebytes;
3249 switch (bmpImage->depth)
3251 case 15:
3252 case 16:
3254 const char* srcbits;
3256 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3258 if (bmpImage->green_mask==0x03e0) {
3259 if (gDst==bmpImage->green_mask) {
3260 if (rDst==bmpImage->red_mask) {
3261 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
3262 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
3263 X11DRV_DIB_Convert_any_asis
3264 (dstwidth,lines,2,
3265 srcbits,-bmpImage->bytes_per_line,
3266 dstbits,linebytes);
3267 } else {
3268 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
3269 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
3270 X11DRV_DIB_Convert_555_reverse
3271 (dstwidth,lines,
3272 srcbits,-bmpImage->bytes_per_line,
3273 dstbits,linebytes);
3275 } else {
3276 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3277 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
3278 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
3279 X11DRV_DIB_Convert_555_to_565_asis
3280 (dstwidth,lines,
3281 srcbits,-bmpImage->bytes_per_line,
3282 dstbits,linebytes);
3283 } else {
3284 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
3285 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
3286 X11DRV_DIB_Convert_555_to_565_reverse
3287 (dstwidth,lines,
3288 srcbits,-bmpImage->bytes_per_line,
3289 dstbits,linebytes);
3292 } else if (bmpImage->green_mask==0x07e0) {
3293 if (gDst==bmpImage->green_mask) {
3294 if (rDst == bmpImage->red_mask) {
3295 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
3296 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
3297 X11DRV_DIB_Convert_any_asis
3298 (dstwidth,lines,2,
3299 srcbits,-bmpImage->bytes_per_line,
3300 dstbits,linebytes);
3301 } else {
3302 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
3303 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
3304 X11DRV_DIB_Convert_565_reverse
3305 (dstwidth,lines,
3306 srcbits,-bmpImage->bytes_per_line,
3307 dstbits,linebytes);
3309 } else {
3310 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3311 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
3312 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
3313 X11DRV_DIB_Convert_565_to_555_asis
3314 (dstwidth,lines,
3315 srcbits,-bmpImage->bytes_per_line,
3316 dstbits,linebytes);
3317 } else {
3318 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
3319 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
3320 X11DRV_DIB_Convert_565_to_555_reverse
3321 (dstwidth,lines,
3322 srcbits,-bmpImage->bytes_per_line,
3323 dstbits,linebytes);
3326 } else {
3327 goto notsupported;
3330 break;
3332 case 24:
3333 if (bmpImage->bits_per_pixel == 24) {
3334 const char* srcbits;
3336 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3338 if (bmpImage->green_mask!=0x00ff00 ||
3339 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3340 goto notsupported;
3341 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3342 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3343 if (gDst==0x03e0) {
3344 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
3345 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
3346 X11DRV_DIB_Convert_888_to_555_asis
3347 (dstwidth,lines,
3348 srcbits,-bmpImage->bytes_per_line,
3349 dstbits,linebytes);
3350 } else {
3351 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3352 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3353 X11DRV_DIB_Convert_888_to_565_asis
3354 (dstwidth,lines,
3355 srcbits,-bmpImage->bytes_per_line,
3356 dstbits,linebytes);
3358 } else {
3359 if (gDst==0x03e0) {
3360 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
3361 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
3362 X11DRV_DIB_Convert_888_to_555_reverse
3363 (dstwidth,lines,
3364 srcbits,-bmpImage->bytes_per_line,
3365 dstbits,linebytes);
3366 } else {
3367 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
3368 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
3369 X11DRV_DIB_Convert_888_to_565_reverse
3370 (dstwidth,lines,
3371 srcbits,-bmpImage->bytes_per_line,
3372 dstbits,linebytes);
3375 break;
3377 /* Fall through */
3379 case 32:
3381 const char* srcbits;
3383 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3385 if (bmpImage->green_mask!=0x00ff00 ||
3386 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3387 goto notsupported;
3388 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3389 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3390 if (gDst==0x03e0) {
3391 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
3392 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
3393 X11DRV_DIB_Convert_0888_to_555_asis
3394 (dstwidth,lines,
3395 srcbits,-bmpImage->bytes_per_line,
3396 dstbits,linebytes);
3397 } else {
3398 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
3399 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
3400 X11DRV_DIB_Convert_0888_to_565_asis
3401 (dstwidth,lines,
3402 srcbits,-bmpImage->bytes_per_line,
3403 dstbits,linebytes);
3405 } else {
3406 if (gDst==0x03e0) {
3407 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
3408 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
3409 X11DRV_DIB_Convert_0888_to_555_reverse
3410 (dstwidth,lines,
3411 srcbits,-bmpImage->bytes_per_line,
3412 dstbits,linebytes);
3413 } else {
3414 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
3415 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
3416 X11DRV_DIB_Convert_0888_to_565_reverse
3417 (dstwidth,lines,
3418 srcbits,-bmpImage->bytes_per_line,
3419 dstbits,linebytes);
3423 break;
3425 case 1:
3426 case 4:
3427 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3428 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
3429 int rShift,gShift,bShift;
3430 WORD* dstpixel;
3432 /* Shift everything 16 bits left so that all shifts are >0,
3433 * even for BGR DIBs. Then a single >> 16 will bring everything
3434 * back into place.
3436 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3437 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3438 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3439 if (gDst==0x07e0) {
3440 /* 6 bits for the green */
3441 gShift++;
3443 rDst=rDst << 16;
3444 gDst=gDst << 16;
3445 bDst=bDst << 16;
3446 for (h = lines - 1; h >= 0; h--) {
3447 dstpixel=(LPWORD)dstbits;
3448 for (x = 0; x < dstwidth; x++) {
3449 PALETTEENTRY srcval;
3450 DWORD dstval;
3451 srcval=srccolors[XGetPixel(bmpImage, x, h)];
3452 dstval=((srcval.peRed << rShift) & rDst) |
3453 ((srcval.peGreen << gShift) & gDst) |
3454 ((srcval.peBlue << bShift) & bDst);
3455 *dstpixel++=dstval >> 16;
3457 dstbits += linebytes;
3459 } else {
3460 goto notsupported;
3462 break;
3464 case 8:
3465 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3466 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
3467 int rShift,gShift,bShift;
3468 const BYTE* srcbits;
3469 const BYTE* srcpixel;
3470 WORD* dstpixel;
3472 /* Shift everything 16 bits left so that all shifts are >0,
3473 * even for BGR DIBs. Then a single >> 16 will bring everything
3474 * back into place.
3476 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3477 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3478 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3479 if (gDst==0x07e0) {
3480 /* 6 bits for the green */
3481 gShift++;
3483 rDst=rDst << 16;
3484 gDst=gDst << 16;
3485 bDst=bDst << 16;
3486 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3487 for (h=0; h<lines; h++) {
3488 srcpixel=srcbits;
3489 dstpixel=(LPWORD)dstbits;
3490 for (x = 0; x < dstwidth; x++) {
3491 PALETTEENTRY srcval;
3492 DWORD dstval;
3493 srcval=srccolors[(int)*srcpixel++];
3494 dstval=((srcval.peRed << rShift) & rDst) |
3495 ((srcval.peGreen << gShift) & gDst) |
3496 ((srcval.peBlue << bShift) & bDst);
3497 *dstpixel++=dstval >> 16;
3499 srcbits -= bmpImage->bytes_per_line;
3500 dstbits += linebytes;
3502 } else {
3503 goto notsupported;
3505 break;
3507 default:
3508 notsupported:
3510 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
3511 int rShift,gShift,bShift;
3512 WORD* dstpixel;
3514 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
3515 bmpImage->depth, bmpImage->red_mask,
3516 bmpImage->green_mask, bmpImage->blue_mask,
3517 rDst, gDst, bDst);
3519 /* Shift everything 16 bits left so that all shifts are >0,
3520 * even for BGR DIBs. Then a single >> 16 will bring everything
3521 * back into place.
3523 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3524 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3525 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3526 if (gDst==0x07e0) {
3527 /* 6 bits for the green */
3528 gShift++;
3530 rDst=rDst << 16;
3531 gDst=gDst << 16;
3532 bDst=bDst << 16;
3533 for (h = lines - 1; h >= 0; h--) {
3534 dstpixel=(LPWORD)dstbits;
3535 for (x = 0; x < dstwidth; x++) {
3536 COLORREF srcval;
3537 DWORD dstval;
3538 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3539 dstval=((GetRValue(srcval) << rShift) & rDst) |
3540 ((GetGValue(srcval) << gShift) & gDst) |
3541 ((GetBValue(srcval) << bShift) & bDst);
3542 *dstpixel++=dstval >> 16;
3544 dstbits += linebytes;
3547 break;
3552 /***********************************************************************
3553 * X11DRV_DIB_SetImageBits_24
3555 * SetDIBits for a 24-bit deep DIB.
3557 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
3558 DWORD srcwidth, DWORD dstwidth, int left,
3559 X11DRV_PDEVICE *physDev,
3560 DWORD rSrc, DWORD gSrc, DWORD bSrc,
3561 XImage *bmpImage, DWORD linebytes )
3563 DWORD x;
3564 int h;
3566 if (lines < 0 )
3568 lines = -lines;
3569 srcbits = srcbits + linebytes * (lines - 1);
3570 linebytes = -linebytes;
3573 switch (bmpImage->depth)
3575 case 24:
3576 if (bmpImage->bits_per_pixel==24) {
3577 char* dstbits;
3579 srcbits=srcbits+left*3;
3580 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3582 if (bmpImage->green_mask!=0x00ff00 ||
3583 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3584 goto notsupported;
3585 } else if (rSrc==bmpImage->red_mask) {
3586 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
3587 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
3588 X11DRV_DIB_Convert_any_asis
3589 (dstwidth,lines,3,
3590 srcbits,linebytes,
3591 dstbits,-bmpImage->bytes_per_line);
3592 } else {
3593 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
3594 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
3595 X11DRV_DIB_Convert_888_reverse
3596 (dstwidth,lines,
3597 srcbits,linebytes,
3598 dstbits,-bmpImage->bytes_per_line);
3600 break;
3602 /* fall through */
3604 case 32:
3606 char* dstbits;
3608 srcbits=srcbits+left*3;
3609 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3611 if (bmpImage->green_mask!=0x00ff00 ||
3612 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3613 goto notsupported;
3614 } else if (rSrc==bmpImage->red_mask) {
3615 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
3616 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
3617 X11DRV_DIB_Convert_888_to_0888_asis
3618 (dstwidth,lines,
3619 srcbits,linebytes,
3620 dstbits,-bmpImage->bytes_per_line);
3621 } else {
3622 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
3623 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
3624 X11DRV_DIB_Convert_888_to_0888_reverse
3625 (dstwidth,lines,
3626 srcbits,linebytes,
3627 dstbits,-bmpImage->bytes_per_line);
3629 break;
3632 case 15:
3633 case 16:
3635 char* dstbits;
3637 srcbits=srcbits+left*3;
3638 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
3640 if (bmpImage->green_mask==0x03e0) {
3641 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
3642 (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3643 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
3644 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
3645 X11DRV_DIB_Convert_888_to_555_asis
3646 (dstwidth,lines,
3647 srcbits,linebytes,
3648 dstbits,-bmpImage->bytes_per_line);
3649 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
3650 (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
3651 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
3652 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
3653 X11DRV_DIB_Convert_888_to_555_reverse
3654 (dstwidth,lines,
3655 srcbits,linebytes,
3656 dstbits,-bmpImage->bytes_per_line);
3657 } else {
3658 goto notsupported;
3660 } else if (bmpImage->green_mask==0x07e0) {
3661 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
3662 (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
3663 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
3664 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
3665 X11DRV_DIB_Convert_888_to_565_asis
3666 (dstwidth,lines,
3667 srcbits,linebytes,
3668 dstbits,-bmpImage->bytes_per_line);
3669 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
3670 (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
3671 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
3672 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
3673 X11DRV_DIB_Convert_888_to_565_reverse
3674 (dstwidth,lines,
3675 srcbits,linebytes,
3676 dstbits,-bmpImage->bytes_per_line);
3677 } else {
3678 goto notsupported;
3680 } else {
3681 goto notsupported;
3684 break;
3686 default:
3687 notsupported:
3688 WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3689 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3690 bmpImage->green_mask, bmpImage->blue_mask );
3691 /* fall through */
3692 case 1:
3693 case 4:
3694 case 8:
3696 /* ==== rgb 888 dib -> any bmp bormat ==== */
3697 const BYTE* srcbyte;
3699 /* Windows only supports one 24bpp DIB format: RGB888 */
3700 srcbits+=left*3;
3701 for (h = lines - 1; h >= 0; h--) {
3702 srcbyte=(const BYTE*)srcbits;
3703 for (x = left; x < dstwidth+left; x++) {
3704 XPutPixel(bmpImage, x, h,
3705 X11DRV_PALETTE_ToPhysical
3706 (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
3707 srcbyte+=3;
3709 srcbits += linebytes;
3712 break;
3717 /***********************************************************************
3718 * X11DRV_DIB_GetImageBits_24
3720 * GetDIBits for an 24-bit deep DIB.
3722 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
3723 DWORD dstwidth, DWORD srcwidth,
3724 PALETTEENTRY *srccolors,
3725 DWORD rDst, DWORD gDst, DWORD bDst,
3726 XImage *bmpImage, DWORD linebytes )
3728 DWORD x;
3729 int h;
3731 if (lines < 0 )
3733 lines = -lines;
3734 dstbits = dstbits + ( linebytes * (lines-1) );
3735 linebytes = -linebytes;
3738 switch (bmpImage->depth)
3740 case 24:
3741 if (bmpImage->bits_per_pixel==24) {
3742 const char* srcbits;
3744 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3746 if (bmpImage->green_mask!=0x00ff00 ||
3747 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3748 goto notsupported;
3749 } else if (rDst==bmpImage->red_mask) {
3750 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
3751 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
3752 X11DRV_DIB_Convert_any_asis
3753 (dstwidth,lines,3,
3754 srcbits,-bmpImage->bytes_per_line,
3755 dstbits,linebytes);
3756 } else {
3757 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
3758 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
3759 X11DRV_DIB_Convert_888_reverse
3760 (dstwidth,lines,
3761 srcbits,-bmpImage->bytes_per_line,
3762 dstbits,linebytes);
3764 break;
3766 /* fall through */
3768 case 32:
3770 const char* srcbits;
3772 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3774 if (bmpImage->green_mask!=0x00ff00 ||
3775 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3776 goto notsupported;
3777 } else if (rDst==bmpImage->red_mask) {
3778 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3779 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3780 X11DRV_DIB_Convert_0888_to_888_asis
3781 (dstwidth,lines,
3782 srcbits,-bmpImage->bytes_per_line,
3783 dstbits,linebytes);
3784 } else {
3785 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3786 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3787 X11DRV_DIB_Convert_0888_to_888_reverse
3788 (dstwidth,lines,
3789 srcbits,-bmpImage->bytes_per_line,
3790 dstbits,linebytes);
3792 break;
3795 case 15:
3796 case 16:
3798 const char* srcbits;
3800 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3802 if (bmpImage->green_mask==0x03e0) {
3803 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
3804 (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3805 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
3806 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
3807 X11DRV_DIB_Convert_555_to_888_asis
3808 (dstwidth,lines,
3809 srcbits,-bmpImage->bytes_per_line,
3810 dstbits,linebytes);
3811 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
3812 (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
3813 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
3814 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
3815 X11DRV_DIB_Convert_555_to_888_reverse
3816 (dstwidth,lines,
3817 srcbits,-bmpImage->bytes_per_line,
3818 dstbits,linebytes);
3819 } else {
3820 goto notsupported;
3822 } else if (bmpImage->green_mask==0x07e0) {
3823 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
3824 (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
3825 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
3826 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
3827 X11DRV_DIB_Convert_565_to_888_asis
3828 (dstwidth,lines,
3829 srcbits,-bmpImage->bytes_per_line,
3830 dstbits,linebytes);
3831 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
3832 (bDst==0xff && bmpImage->blue_mask==0xf800)) {
3833 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
3834 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
3835 X11DRV_DIB_Convert_565_to_888_reverse
3836 (dstwidth,lines,
3837 srcbits,-bmpImage->bytes_per_line,
3838 dstbits,linebytes);
3839 } else {
3840 goto notsupported;
3842 } else {
3843 goto notsupported;
3846 break;
3848 case 1:
3849 case 4:
3850 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3851 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
3852 BYTE* dstbyte;
3854 /* Windows only supports one 24bpp DIB format: rgb 888 */
3855 for (h = lines - 1; h >= 0; h--) {
3856 dstbyte=dstbits;
3857 for (x = 0; x < dstwidth; x++) {
3858 PALETTEENTRY srcval;
3859 srcval=srccolors[XGetPixel(bmpImage, x, h)];
3860 dstbyte[0]=srcval.peBlue;
3861 dstbyte[1]=srcval.peGreen;
3862 dstbyte[2]=srcval.peRed;
3863 dstbyte+=3;
3865 dstbits += linebytes;
3867 } else {
3868 goto notsupported;
3870 break;
3872 case 8:
3873 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors) {
3874 /* ==== pal 8 bmp -> rgb 888 dib ==== */
3875 const void* srcbits;
3876 const BYTE* srcpixel;
3877 BYTE* dstbyte;
3879 /* Windows only supports one 24bpp DIB format: rgb 888 */
3880 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3881 for (h = lines - 1; h >= 0; h--) {
3882 srcpixel=srcbits;
3883 dstbyte=dstbits;
3884 for (x = 0; x < dstwidth; x++ ) {
3885 PALETTEENTRY srcval;
3886 srcval=srccolors[(int)*srcpixel++];
3887 dstbyte[0]=srcval.peBlue;
3888 dstbyte[1]=srcval.peGreen;
3889 dstbyte[2]=srcval.peRed;
3890 dstbyte+=3;
3892 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
3893 dstbits += linebytes;
3895 } else {
3896 goto notsupported;
3898 break;
3900 default:
3901 notsupported:
3903 /* ==== any bmp format -> 888 dib ==== */
3904 BYTE* dstbyte;
3906 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
3907 bmpImage->depth, bmpImage->red_mask,
3908 bmpImage->green_mask, bmpImage->blue_mask,
3909 rDst, gDst, bDst );
3911 /* Windows only supports one 24bpp DIB format: rgb 888 */
3912 for (h = lines - 1; h >= 0; h--) {
3913 dstbyte=dstbits;
3914 for (x = 0; x < dstwidth; x++) {
3915 COLORREF srcval=X11DRV_PALETTE_ToLogical
3916 (XGetPixel( bmpImage, x, h ));
3917 dstbyte[0]=GetBValue(srcval);
3918 dstbyte[1]=GetGValue(srcval);
3919 dstbyte[2]=GetRValue(srcval);
3920 dstbyte+=3;
3922 dstbits += linebytes;
3925 break;
3930 /***********************************************************************
3931 * X11DRV_DIB_SetImageBits_32
3933 * SetDIBits for a 32-bit deep DIB.
3935 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
3936 DWORD srcwidth, DWORD dstwidth, int left,
3937 X11DRV_PDEVICE *physDev,
3938 DWORD rSrc, DWORD gSrc, DWORD bSrc,
3939 XImage *bmpImage,
3940 DWORD linebytes)
3942 DWORD x, *ptr;
3943 int h;
3945 if (lines < 0 )
3947 lines = -lines;
3948 srcbits = srcbits + ( linebytes * (lines-1) );
3949 linebytes = -linebytes;
3952 ptr = (DWORD *) srcbits + left;
3954 switch (bmpImage->depth)
3956 case 24:
3957 if (bmpImage->bits_per_pixel==24) {
3958 char* dstbits;
3960 srcbits=srcbits+left*4;
3961 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3963 if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
3964 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
3965 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
3966 X11DRV_DIB_Convert_0888_to_888_asis
3967 (dstwidth,lines,
3968 srcbits,linebytes,
3969 dstbits,-bmpImage->bytes_per_line);
3970 } else if (bmpImage->green_mask!=0x00ff00 ||
3971 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3972 goto notsupported;
3973 /* the tests below assume sane bmpImage masks */
3974 } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
3975 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
3976 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
3977 X11DRV_DIB_Convert_0888_to_888_reverse
3978 (dstwidth,lines,
3979 srcbits,linebytes,
3980 dstbits,-bmpImage->bytes_per_line);
3981 } else if (bmpImage->blue_mask==0xff) {
3982 /* ==== any 0888 dib -> rgb 888 bmp ==== */
3983 X11DRV_DIB_Convert_any0888_to_rgb888
3984 (dstwidth,lines,
3985 srcbits,linebytes,
3986 rSrc,gSrc,bSrc,
3987 dstbits,-bmpImage->bytes_per_line);
3988 } else {
3989 /* ==== any 0888 dib -> bgr 888 bmp ==== */
3990 X11DRV_DIB_Convert_any0888_to_bgr888
3991 (dstwidth,lines,
3992 srcbits,linebytes,
3993 rSrc,gSrc,bSrc,
3994 dstbits,-bmpImage->bytes_per_line);
3996 break;
3998 /* fall through */
4000 case 32:
4002 char* dstbits;
4004 srcbits=srcbits+left*4;
4005 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
4007 if (gSrc==bmpImage->green_mask) {
4008 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
4009 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
4010 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
4011 X11DRV_DIB_Convert_any_asis
4012 (dstwidth,lines,4,
4013 srcbits,linebytes,
4014 dstbits,-bmpImage->bytes_per_line);
4015 } else if (bmpImage->green_mask!=0x00ff00 ||
4016 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4017 goto notsupported;
4018 /* the tests below assume sane bmpImage masks */
4019 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
4020 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
4021 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
4022 X11DRV_DIB_Convert_0888_reverse
4023 (dstwidth,lines,
4024 srcbits,linebytes,
4025 dstbits,-bmpImage->bytes_per_line);
4026 } else {
4027 /* ==== any 0888 dib -> any 0888 bmp ==== */
4028 X11DRV_DIB_Convert_0888_any
4029 (dstwidth,lines,
4030 srcbits,linebytes,
4031 rSrc,gSrc,bSrc,
4032 dstbits,-bmpImage->bytes_per_line,
4033 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4035 } else if (bmpImage->green_mask!=0x00ff00 ||
4036 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4037 goto notsupported;
4038 /* the tests below assume sane bmpImage masks */
4039 } else {
4040 /* ==== any 0888 dib -> any 0888 bmp ==== */
4041 X11DRV_DIB_Convert_0888_any
4042 (dstwidth,lines,
4043 srcbits,linebytes,
4044 rSrc,gSrc,bSrc,
4045 dstbits,-bmpImage->bytes_per_line,
4046 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4049 break;
4051 case 15:
4052 case 16:
4054 char* dstbits;
4056 srcbits=srcbits+left*4;
4057 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
4059 if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
4060 if (bmpImage->green_mask==0x03e0) {
4061 if (bmpImage->red_mask==0x7f00) {
4062 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
4063 X11DRV_DIB_Convert_0888_to_555_asis
4064 (dstwidth,lines,
4065 srcbits,linebytes,
4066 dstbits,-bmpImage->bytes_per_line);
4067 } else if (bmpImage->blue_mask==0x7f00) {
4068 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
4069 X11DRV_DIB_Convert_0888_to_555_reverse
4070 (dstwidth,lines,
4071 srcbits,linebytes,
4072 dstbits,-bmpImage->bytes_per_line);
4073 } else {
4074 goto notsupported;
4076 } else if (bmpImage->green_mask==0x07e0) {
4077 if (bmpImage->red_mask==0xf800) {
4078 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
4079 X11DRV_DIB_Convert_0888_to_565_asis
4080 (dstwidth,lines,
4081 srcbits,linebytes,
4082 dstbits,-bmpImage->bytes_per_line);
4083 } else if (bmpImage->blue_mask==0xf800) {
4084 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
4085 X11DRV_DIB_Convert_0888_to_565_reverse
4086 (dstwidth,lines,
4087 srcbits,linebytes,
4088 dstbits,-bmpImage->bytes_per_line);
4089 } else {
4090 goto notsupported;
4092 } else {
4093 goto notsupported;
4095 } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
4096 if (bmpImage->green_mask==0x03e0) {
4097 if (bmpImage->blue_mask==0x7f00) {
4098 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
4099 X11DRV_DIB_Convert_0888_to_555_asis
4100 (dstwidth,lines,
4101 srcbits,linebytes,
4102 dstbits,-bmpImage->bytes_per_line);
4103 } else if (bmpImage->red_mask==0x7f00) {
4104 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
4105 X11DRV_DIB_Convert_0888_to_555_reverse
4106 (dstwidth,lines,
4107 srcbits,linebytes,
4108 dstbits,-bmpImage->bytes_per_line);
4109 } else {
4110 goto notsupported;
4112 } else if (bmpImage->green_mask==0x07e0) {
4113 if (bmpImage->blue_mask==0xf800) {
4114 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
4115 X11DRV_DIB_Convert_0888_to_565_asis
4116 (dstwidth,lines,
4117 srcbits,linebytes,
4118 dstbits,-bmpImage->bytes_per_line);
4119 } else if (bmpImage->red_mask==0xf800) {
4120 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
4121 X11DRV_DIB_Convert_0888_to_565_reverse
4122 (dstwidth,lines,
4123 srcbits,linebytes,
4124 dstbits,-bmpImage->bytes_per_line);
4125 } else {
4126 goto notsupported;
4128 } else {
4129 goto notsupported;
4131 } else {
4132 if (bmpImage->green_mask==0x03e0 &&
4133 (bmpImage->red_mask==0x7f00 ||
4134 bmpImage->blue_mask==0x7f00)) {
4135 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
4136 X11DRV_DIB_Convert_any0888_to_5x5
4137 (dstwidth,lines,
4138 srcbits,linebytes,
4139 rSrc,gSrc,bSrc,
4140 dstbits,-bmpImage->bytes_per_line,
4141 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4142 } else if (bmpImage->green_mask==0x07e0 &&
4143 (bmpImage->red_mask==0xf800 ||
4144 bmpImage->blue_mask==0xf800)) {
4145 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
4146 X11DRV_DIB_Convert_any0888_to_5x5
4147 (dstwidth,lines,
4148 srcbits,linebytes,
4149 rSrc,gSrc,bSrc,
4150 dstbits,-bmpImage->bytes_per_line,
4151 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4152 } else {
4153 goto notsupported;
4157 break;
4159 default:
4160 notsupported:
4161 WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
4162 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
4163 bmpImage->green_mask, bmpImage->blue_mask );
4164 /* fall through */
4165 case 1:
4166 case 4:
4167 case 8:
4169 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
4170 const DWORD* srcpixel;
4171 int rShift,gShift,bShift;
4173 rShift=X11DRV_DIB_MaskToShift(rSrc);
4174 gShift=X11DRV_DIB_MaskToShift(gSrc);
4175 bShift=X11DRV_DIB_MaskToShift(bSrc);
4176 srcbits+=left*4;
4177 for (h = lines - 1; h >= 0; h--) {
4178 srcpixel=(const DWORD*)srcbits;
4179 for (x = left; x < dstwidth+left; x++) {
4180 DWORD srcvalue;
4181 BYTE red,green,blue;
4182 srcvalue=*srcpixel++;
4183 red= (srcvalue >> rShift) & 0xff;
4184 green=(srcvalue >> gShift) & 0xff;
4185 blue= (srcvalue >> bShift) & 0xff;
4186 XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
4187 (physDev, RGB(red,green,blue)));
4189 srcbits += linebytes;
4192 break;
4197 /***********************************************************************
4198 * X11DRV_DIB_GetImageBits_32
4200 * GetDIBits for an 32-bit deep DIB.
4202 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
4203 DWORD dstwidth, DWORD srcwidth,
4204 PALETTEENTRY *srccolors,
4205 DWORD rDst, DWORD gDst, DWORD bDst,
4206 XImage *bmpImage, DWORD linebytes )
4208 DWORD x;
4209 int h;
4210 BYTE *bits;
4212 if (lines < 0 )
4214 lines = -lines;
4215 dstbits = dstbits + ( linebytes * (lines-1) );
4216 linebytes = -linebytes;
4219 bits = dstbits;
4221 switch (bmpImage->depth)
4223 case 24:
4224 if (bmpImage->bits_per_pixel==24) {
4225 const void* srcbits;
4227 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4229 if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
4230 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
4231 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
4232 X11DRV_DIB_Convert_888_to_0888_asis
4233 (dstwidth,lines,
4234 srcbits,-bmpImage->bytes_per_line,
4235 dstbits,linebytes);
4236 } else if (bmpImage->green_mask!=0x00ff00 ||
4237 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4238 goto notsupported;
4239 /* the tests below assume sane bmpImage masks */
4240 } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
4241 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
4242 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
4243 X11DRV_DIB_Convert_888_to_0888_reverse
4244 (dstwidth,lines,
4245 srcbits,-bmpImage->bytes_per_line,
4246 dstbits,linebytes);
4247 } else if (bmpImage->blue_mask==0xff) {
4248 /* ==== rgb 888 bmp -> any 0888 dib ==== */
4249 X11DRV_DIB_Convert_rgb888_to_any0888
4250 (dstwidth,lines,
4251 srcbits,-bmpImage->bytes_per_line,
4252 dstbits,linebytes,
4253 rDst,gDst,bDst);
4254 } else {
4255 /* ==== bgr 888 bmp -> any 0888 dib ==== */
4256 X11DRV_DIB_Convert_bgr888_to_any0888
4257 (dstwidth,lines,
4258 srcbits,-bmpImage->bytes_per_line,
4259 dstbits,linebytes,
4260 rDst,gDst,bDst);
4262 break;
4264 /* fall through */
4266 case 32:
4268 const char* srcbits;
4270 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4272 if (gDst==bmpImage->green_mask) {
4273 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
4274 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
4275 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
4276 X11DRV_DIB_Convert_any_asis
4277 (dstwidth,lines,4,
4278 srcbits,-bmpImage->bytes_per_line,
4279 dstbits,linebytes);
4280 } else if (bmpImage->green_mask!=0x00ff00 ||
4281 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4282 goto notsupported;
4283 /* the tests below assume sane bmpImage masks */
4284 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
4285 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
4286 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
4287 X11DRV_DIB_Convert_0888_reverse
4288 (dstwidth,lines,
4289 srcbits,-bmpImage->bytes_per_line,
4290 dstbits,linebytes);
4291 } else {
4292 /* ==== any 0888 bmp -> any 0888 dib ==== */
4293 X11DRV_DIB_Convert_0888_any
4294 (dstwidth,lines,
4295 srcbits,-bmpImage->bytes_per_line,
4296 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4297 dstbits,linebytes,
4298 rDst,gDst,bDst);
4300 } else if (bmpImage->green_mask!=0x00ff00 ||
4301 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4302 goto notsupported;
4303 /* the tests below assume sane bmpImage masks */
4304 } else {
4305 /* ==== any 0888 bmp -> any 0888 dib ==== */
4306 X11DRV_DIB_Convert_0888_any
4307 (dstwidth,lines,
4308 srcbits,-bmpImage->bytes_per_line,
4309 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4310 dstbits,linebytes,
4311 rDst,gDst,bDst);
4314 break;
4316 case 15:
4317 case 16:
4319 const char* srcbits;
4321 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4323 if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
4324 if (bmpImage->green_mask==0x03e0) {
4325 if (bmpImage->red_mask==0x7f00) {
4326 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
4327 X11DRV_DIB_Convert_555_to_0888_asis
4328 (dstwidth,lines,
4329 srcbits,-bmpImage->bytes_per_line,
4330 dstbits,linebytes);
4331 } else if (bmpImage->blue_mask==0x7f00) {
4332 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
4333 X11DRV_DIB_Convert_555_to_0888_reverse
4334 (dstwidth,lines,
4335 srcbits,-bmpImage->bytes_per_line,
4336 dstbits,linebytes);
4337 } else {
4338 goto notsupported;
4340 } else if (bmpImage->green_mask==0x07e0) {
4341 if (bmpImage->red_mask==0xf800) {
4342 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
4343 X11DRV_DIB_Convert_565_to_0888_asis
4344 (dstwidth,lines,
4345 srcbits,-bmpImage->bytes_per_line,
4346 dstbits,linebytes);
4347 } else if (bmpImage->blue_mask==0xf800) {
4348 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
4349 X11DRV_DIB_Convert_565_to_0888_reverse
4350 (dstwidth,lines,
4351 srcbits,-bmpImage->bytes_per_line,
4352 dstbits,linebytes);
4353 } else {
4354 goto notsupported;
4356 } else {
4357 goto notsupported;
4359 } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
4360 if (bmpImage->green_mask==0x03e0) {
4361 if (bmpImage->blue_mask==0x7f00) {
4362 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
4363 X11DRV_DIB_Convert_555_to_0888_asis
4364 (dstwidth,lines,
4365 srcbits,-bmpImage->bytes_per_line,
4366 dstbits,linebytes);
4367 } else if (bmpImage->red_mask==0x7f00) {
4368 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
4369 X11DRV_DIB_Convert_555_to_0888_reverse
4370 (dstwidth,lines,
4371 srcbits,-bmpImage->bytes_per_line,
4372 dstbits,linebytes);
4373 } else {
4374 goto notsupported;
4376 } else if (bmpImage->green_mask==0x07e0) {
4377 if (bmpImage->blue_mask==0xf800) {
4378 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
4379 X11DRV_DIB_Convert_565_to_0888_asis
4380 (dstwidth,lines,
4381 srcbits,-bmpImage->bytes_per_line,
4382 dstbits,linebytes);
4383 } else if (bmpImage->red_mask==0xf800) {
4384 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
4385 X11DRV_DIB_Convert_565_to_0888_reverse
4386 (dstwidth,lines,
4387 srcbits,-bmpImage->bytes_per_line,
4388 dstbits,linebytes);
4389 } else {
4390 goto notsupported;
4392 } else {
4393 goto notsupported;
4395 } else {
4396 if (bmpImage->green_mask==0x03e0 &&
4397 (bmpImage->red_mask==0x7f00 ||
4398 bmpImage->blue_mask==0x7f00)) {
4399 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
4400 X11DRV_DIB_Convert_5x5_to_any0888
4401 (dstwidth,lines,
4402 srcbits,-bmpImage->bytes_per_line,
4403 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4404 dstbits,linebytes,
4405 rDst,gDst,bDst);
4406 } else if (bmpImage->green_mask==0x07e0 &&
4407 (bmpImage->red_mask==0xf800 ||
4408 bmpImage->blue_mask==0xf800)) {
4409 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
4410 X11DRV_DIB_Convert_5x5_to_any0888
4411 (dstwidth,lines,
4412 srcbits,-bmpImage->bytes_per_line,
4413 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4414 dstbits,linebytes,
4415 rDst,gDst,bDst);
4416 } else {
4417 goto notsupported;
4421 break;
4423 case 1:
4424 case 4:
4425 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4426 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
4427 int rShift,gShift,bShift;
4428 DWORD* dstpixel;
4430 rShift=X11DRV_DIB_MaskToShift(rDst);
4431 gShift=X11DRV_DIB_MaskToShift(gDst);
4432 bShift=X11DRV_DIB_MaskToShift(bDst);
4433 for (h = lines - 1; h >= 0; h--) {
4434 dstpixel=(DWORD*)dstbits;
4435 for (x = 0; x < dstwidth; x++) {
4436 PALETTEENTRY srcval;
4437 srcval = srccolors[XGetPixel(bmpImage, x, h)];
4438 *dstpixel++=(srcval.peRed << rShift) |
4439 (srcval.peGreen << gShift) |
4440 (srcval.peBlue << bShift);
4442 dstbits += linebytes;
4444 } else {
4445 goto notsupported;
4447 break;
4449 case 8:
4450 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4451 /* ==== pal 8 bmp -> any 0888 dib ==== */
4452 int rShift,gShift,bShift;
4453 const void* srcbits;
4454 const BYTE* srcpixel;
4455 DWORD* dstpixel;
4457 rShift=X11DRV_DIB_MaskToShift(rDst);
4458 gShift=X11DRV_DIB_MaskToShift(gDst);
4459 bShift=X11DRV_DIB_MaskToShift(bDst);
4460 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4461 for (h = lines - 1; h >= 0; h--) {
4462 srcpixel=srcbits;
4463 dstpixel=(DWORD*)dstbits;
4464 for (x = 0; x < dstwidth; x++) {
4465 PALETTEENTRY srcval;
4466 srcval=srccolors[(int)*srcpixel++];
4467 *dstpixel++=(srcval.peRed << rShift) |
4468 (srcval.peGreen << gShift) |
4469 (srcval.peBlue << bShift);
4471 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
4472 dstbits += linebytes;
4474 } else {
4475 goto notsupported;
4477 break;
4479 default:
4480 notsupported:
4482 /* ==== any bmp format -> any 0888 dib ==== */
4483 int rShift,gShift,bShift;
4484 DWORD* dstpixel;
4486 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
4487 bmpImage->depth, bmpImage->red_mask,
4488 bmpImage->green_mask, bmpImage->blue_mask,
4489 rDst,gDst,bDst);
4491 rShift=X11DRV_DIB_MaskToShift(rDst);
4492 gShift=X11DRV_DIB_MaskToShift(gDst);
4493 bShift=X11DRV_DIB_MaskToShift(bDst);
4494 for (h = lines - 1; h >= 0; h--) {
4495 dstpixel=(DWORD*)dstbits;
4496 for (x = 0; x < dstwidth; x++) {
4497 COLORREF srcval;
4498 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
4499 *dstpixel++=(GetRValue(srcval) << rShift) |
4500 (GetGValue(srcval) << gShift) |
4501 (GetBValue(srcval) << bShift);
4503 dstbits += linebytes;
4506 break;
4510 /***********************************************************************
4511 * X11DRV_DIB_SetImageBits
4513 * Transfer the bits to an X image.
4514 * Helper function for SetDIBits() and SetDIBitsToDevice().
4516 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4518 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4519 XImage *bmpImage;
4521 wine_tsx11_lock();
4522 if (descr->image)
4523 bmpImage = descr->image;
4524 else {
4525 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4526 descr->infoWidth, lines, 32, 0 );
4527 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4528 if(bmpImage->data == NULL) {
4529 ERR("Out of memory!\n");
4530 XDestroyImage( bmpImage );
4531 wine_tsx11_unlock();
4532 return lines;
4536 TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
4537 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4538 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
4539 bmpImage->depth,bmpImage->bits_per_pixel,
4540 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4542 /* Transfer the pixels */
4543 switch(descr->infoBpp)
4545 case 1:
4546 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
4547 descr->width, descr->xSrc, (int *)(descr->colorMap),
4548 bmpImage, descr->dibpitch );
4549 break;
4550 case 4:
4551 if (descr->compression) {
4552 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4553 descr->width, descr->height, AllPlanes, ZPixmap,
4554 bmpImage, descr->xSrc, descr->ySrc );
4556 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
4557 descr->infoWidth, descr->width,
4558 descr->xSrc, (int *)(descr->colorMap),
4559 bmpImage );
4560 } else
4561 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
4562 descr->infoWidth, descr->width,
4563 descr->xSrc, (int*)(descr->colorMap),
4564 bmpImage, descr->dibpitch );
4565 break;
4566 case 8:
4567 if (descr->compression) {
4568 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4569 descr->width, descr->height, AllPlanes, ZPixmap,
4570 bmpImage, descr->xSrc, descr->ySrc );
4571 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
4572 descr->infoWidth, descr->width,
4573 descr->xSrc, (int *)(descr->colorMap),
4574 bmpImage );
4575 } else
4576 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
4577 descr->infoWidth, descr->width,
4578 descr->xSrc, (int *)(descr->colorMap),
4579 bmpImage, descr->dibpitch );
4580 break;
4581 case 15:
4582 case 16:
4583 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
4584 descr->infoWidth, descr->width,
4585 descr->xSrc, descr->physDev,
4586 descr->rMask, descr->gMask, descr->bMask,
4587 bmpImage, descr->dibpitch);
4588 break;
4589 case 24:
4590 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
4591 descr->infoWidth, descr->width,
4592 descr->xSrc, descr->physDev,
4593 descr->rMask, descr->gMask, descr->bMask,
4594 bmpImage, descr->dibpitch);
4595 break;
4596 case 32:
4597 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
4598 descr->infoWidth, descr->width,
4599 descr->xSrc, descr->physDev,
4600 descr->rMask, descr->gMask, descr->bMask,
4601 bmpImage, descr->dibpitch);
4602 break;
4603 default:
4604 WARN("(%d): Invalid depth\n", descr->infoBpp );
4605 break;
4608 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
4609 descr->drawable, descr->gc, bmpImage,
4610 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4611 descr->width, descr->height);
4612 #ifdef HAVE_LIBXXSHM
4613 if (descr->useShm)
4615 XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4616 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4617 descr->width, descr->height, FALSE );
4618 XSync( gdi_display, 0 );
4620 else
4621 #endif
4622 XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4623 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4624 descr->width, descr->height );
4626 if (!descr->image) XDestroyImage( bmpImage );
4627 wine_tsx11_unlock();
4628 return lines;
4631 /***********************************************************************
4632 * X11DRV_DIB_GetImageBits
4634 * Transfer the bits from an X image.
4636 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4638 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4639 XImage *bmpImage;
4641 wine_tsx11_lock();
4642 if (descr->image)
4643 bmpImage = descr->image;
4644 else {
4645 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4646 descr->infoWidth, lines, 32, 0 );
4647 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4648 if(bmpImage->data == NULL) {
4649 ERR("Out of memory!\n");
4650 XDestroyImage( bmpImage );
4651 wine_tsx11_unlock();
4652 return lines;
4656 #ifdef HAVE_LIBXXSHM
4657 if (descr->useShm)
4659 int saveRed, saveGreen, saveBlue;
4661 TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
4662 gdi_display, descr->drawable, bmpImage,
4663 descr->xSrc, descr->ySrc, AllPlanes);
4665 /* We must save and restore the bmpImage's masks in order
4666 * to preserve them across the call to XShmGetImage, which
4667 * decides to eleminate them since it doesn't happen to know
4668 * what the format of the image is supposed to be, even though
4669 * we do. */
4670 saveRed = bmpImage->red_mask;
4671 saveBlue= bmpImage->blue_mask;
4672 saveGreen = bmpImage->green_mask;
4674 XShmGetImage( gdi_display, descr->drawable, bmpImage,
4675 descr->xSrc, descr->ySrc, AllPlanes);
4677 bmpImage->red_mask = saveRed;
4678 bmpImage->blue_mask = saveBlue;
4679 bmpImage->green_mask = saveGreen;
4681 else
4682 #endif /* HAVE_LIBXXSHM */
4684 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
4685 gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
4686 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
4687 XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
4688 descr->width, lines, AllPlanes, ZPixmap,
4689 bmpImage, descr->xDest, descr->yDest );
4692 TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
4693 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4694 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
4695 bmpImage->depth,bmpImage->bits_per_pixel,
4696 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4697 /* Transfer the pixels */
4698 switch(descr->infoBpp)
4700 case 1:
4701 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
4702 descr->infoWidth, descr->width,
4703 descr->colorMap, descr->palentry,
4704 bmpImage, descr->dibpitch );
4705 break;
4707 case 4:
4708 if (descr->compression)
4709 FIXME("Compression not yet supported!\n");
4710 else
4711 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
4712 descr->infoWidth, descr->width,
4713 descr->colorMap, descr->palentry,
4714 bmpImage, descr->dibpitch );
4715 break;
4717 case 8:
4718 if (descr->compression)
4719 FIXME("Compression not yet supported!\n");
4720 else
4721 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
4722 descr->infoWidth, descr->width,
4723 descr->colorMap, descr->palentry,
4724 bmpImage, descr->dibpitch );
4725 break;
4726 case 15:
4727 case 16:
4728 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
4729 descr->infoWidth,descr->width,
4730 descr->palentry,
4731 descr->rMask, descr->gMask, descr->bMask,
4732 bmpImage, descr->dibpitch );
4733 break;
4735 case 24:
4736 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
4737 descr->infoWidth,descr->width,
4738 descr->palentry,
4739 descr->rMask, descr->gMask, descr->bMask,
4740 bmpImage, descr->dibpitch);
4741 break;
4743 case 32:
4744 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
4745 descr->infoWidth, descr->width,
4746 descr->palentry,
4747 descr->rMask, descr->gMask, descr->bMask,
4748 bmpImage, descr->dibpitch);
4749 break;
4751 default:
4752 WARN("(%d): Invalid depth\n", descr->infoBpp );
4753 break;
4756 if (!descr->image) XDestroyImage( bmpImage );
4757 wine_tsx11_unlock();
4758 return lines;
4761 /*************************************************************************
4762 * X11DRV_SetDIBitsToDevice
4765 INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWORD cx,
4766 DWORD cy, INT xSrc, INT ySrc,
4767 UINT startscan, UINT lines, LPCVOID bits,
4768 const BITMAPINFO *info, UINT coloruse )
4770 X11DRV_DIB_IMAGEBITS_DESCR descr;
4771 DWORD width;
4772 INT result;
4773 int height;
4774 BOOL top_down;
4775 POINT pt;
4776 DC *dc = physDev->dc;
4778 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
4779 &descr.infoBpp, &descr.compression ) == -1)
4780 return 0;
4781 top_down = (height < 0);
4782 if (top_down) height = -height;
4784 pt.x = xDest;
4785 pt.y = yDest;
4786 LPtoDP(physDev->hdc, &pt, 1);
4788 if (!lines || (startscan >= height)) return 0;
4789 if (!top_down && startscan + lines > height) lines = height - startscan;
4791 /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
4792 * and clamp all values to fit inside [startscan,startscan+lines]
4794 if (ySrc + cy <= startscan + lines)
4796 INT y = startscan + lines - (ySrc + cy);
4797 if (ySrc < startscan) cy -= (startscan - ySrc);
4798 if (!top_down)
4800 /* avoid getting unnecessary lines */
4801 ySrc = 0;
4802 if (y >= lines) return 0;
4803 lines -= y;
4805 else
4807 if (y >= lines) return lines;
4808 ySrc = y; /* need to get all lines in top down mode */
4811 else
4813 if (ySrc >= startscan + lines) return lines;
4814 pt.y += ySrc + cy - (startscan + lines);
4815 cy = startscan + lines - ySrc;
4816 ySrc = 0;
4817 if (cy > lines) cy = lines;
4819 if (xSrc >= width) return lines;
4820 if (xSrc + cx >= width) cx = width - xSrc;
4821 if (!cx || !cy) return lines;
4823 X11DRV_SetupGCForText( physDev ); /* To have the correct colors */
4824 TSXSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
4826 switch (descr.infoBpp)
4828 case 1:
4829 case 4:
4830 case 8:
4831 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4832 coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
4833 dc->bitsPerPixel, info, &descr.nColorMap );
4834 if (!descr.colorMap) return 0;
4835 descr.rMask = descr.gMask = descr.bMask = 0;
4836 break;
4837 case 15:
4838 case 16:
4839 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4840 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4841 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4842 descr.colorMap = 0;
4843 break;
4845 case 24:
4846 case 32:
4847 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
4848 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4849 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4850 descr.colorMap = 0;
4851 break;
4854 descr.physDev = physDev;
4855 descr.bits = bits;
4856 descr.image = NULL;
4857 descr.palentry = NULL;
4858 descr.lines = top_down ? -lines : lines;
4859 descr.infoWidth = width;
4860 descr.depth = dc->bitsPerPixel;
4861 descr.drawable = physDev->drawable;
4862 descr.gc = physDev->gc;
4863 descr.xSrc = xSrc;
4864 descr.ySrc = ySrc;
4865 descr.xDest = physDev->org.x + pt.x;
4866 descr.yDest = physDev->org.y + pt.y;
4867 descr.width = cx;
4868 descr.height = cy;
4869 descr.useShm = FALSE;
4870 descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
4872 result = X11DRV_DIB_SetImageBits( &descr );
4874 if (descr.infoBpp <= 8)
4875 HeapFree(GetProcessHeap(), 0, descr.colorMap);
4876 return result;
4879 /***********************************************************************
4880 * SetDIBits (X11DRV.@)
4882 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
4883 UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
4885 X11DRV_DIB_IMAGEBITS_DESCR descr;
4886 BITMAPOBJ *bmp;
4887 int height, tmpheight;
4888 INT result;
4890 descr.physDev = physDev;
4892 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
4893 &descr.infoBpp, &descr.compression ) == -1)
4894 return 0;
4896 tmpheight = height;
4897 if (height < 0) height = -height;
4898 if (!lines || (startscan >= height))
4899 return 0;
4901 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
4903 if (startscan + lines > height) lines = height - startscan;
4905 switch (descr.infoBpp)
4907 case 1:
4908 case 4:
4909 case 8:
4910 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4911 coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
4912 bmp->bitmap.bmBitsPixel,
4913 info, &descr.nColorMap );
4914 if (!descr.colorMap)
4916 GDI_ReleaseObj( hbitmap );
4917 return 0;
4919 descr.rMask = descr.gMask = descr.bMask = 0;
4920 break;
4921 case 15:
4922 case 16:
4923 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4924 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4925 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4926 descr.colorMap = 0;
4927 break;
4929 case 24:
4930 case 32:
4931 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
4932 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4933 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4934 descr.colorMap = 0;
4935 break;
4937 default: break;
4940 descr.bits = bits;
4941 descr.image = NULL;
4942 descr.palentry = NULL;
4943 descr.lines = tmpheight >= 0 ? lines : -lines;
4944 descr.depth = bmp->bitmap.bmBitsPixel;
4945 descr.drawable = (Pixmap)bmp->physBitmap;
4946 descr.gc = BITMAP_GC(bmp);
4947 descr.xSrc = 0;
4948 descr.ySrc = 0;
4949 descr.xDest = 0;
4950 descr.yDest = height - startscan - lines;
4951 descr.width = bmp->bitmap.bmWidth;
4952 descr.height = lines;
4953 descr.useShm = FALSE;
4954 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
4955 X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
4956 result = X11DRV_DIB_SetImageBits( &descr );
4957 X11DRV_DIB_Unlock(bmp, TRUE);
4959 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
4961 GDI_ReleaseObj( hbitmap );
4962 return result;
4965 /***********************************************************************
4966 * GetDIBits (X11DRV.@)
4968 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
4969 LPVOID bits, BITMAPINFO *info, UINT coloruse )
4971 X11DRV_DIBSECTION *dib;
4972 X11DRV_DIB_IMAGEBITS_DESCR descr;
4973 PALETTEOBJ * palette;
4974 BITMAPOBJ *bmp;
4975 int height;
4976 DC *dc = physDev->dc;
4978 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
4979 return 0;
4980 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
4982 GDI_ReleaseObj( dc->hPalette );
4983 return 0;
4985 dib = (X11DRV_DIBSECTION *) bmp->dib;
4987 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
4988 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
4989 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
4990 startscan );
4992 if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
4994 height = info->bmiHeader.biHeight;
4995 if (height < 0) height = -height;
4996 if( lines > height ) lines = height;
4997 /* Top-down images have a negative biHeight, the scanlines of theses images
4998 * were inverted in X11DRV_DIB_GetImageBits_xx
4999 * To prevent this we simply change the sign of lines
5000 * (the number of scan lines to copy).
5001 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
5003 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
5005 if( startscan >= bmp->bitmap.bmHeight )
5007 lines = 0;
5008 goto done;
5011 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
5012 &descr.infoBpp, &descr.compression ) == -1)
5014 lines = 0;
5015 goto done;
5018 switch (descr.infoBpp)
5020 case 1:
5021 case 4:
5022 case 8:
5023 descr.rMask= descr.gMask = descr.bMask = 0;
5024 break;
5025 case 15:
5026 case 16:
5027 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
5028 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
5029 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
5030 break;
5031 case 24:
5032 case 32:
5033 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
5034 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
5035 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
5036 break;
5039 descr.physDev = physDev;
5040 descr.palentry = palette->logpalette.palPalEntry;
5041 descr.bits = bits;
5042 descr.image = NULL;
5043 descr.lines = lines;
5044 descr.depth = bmp->bitmap.bmBitsPixel;
5045 descr.drawable = (Pixmap)bmp->physBitmap;
5046 descr.gc = BITMAP_GC(bmp);
5047 descr.width = bmp->bitmap.bmWidth;
5048 descr.height = bmp->bitmap.bmHeight;
5049 descr.colorMap = info->bmiColors;
5050 descr.xDest = 0;
5051 descr.yDest = 0;
5052 descr.xSrc = 0;
5054 if (descr.lines > 0)
5056 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
5058 else
5060 descr.ySrc = startscan;
5062 #ifdef HAVE_LIBXXSHM
5063 descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
5064 #else
5065 descr.useShm = FALSE;
5066 #endif
5067 descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
5068 : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
5070 X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
5071 X11DRV_DIB_GetImageBits( &descr );
5072 X11DRV_DIB_Unlock(bmp, TRUE);
5074 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
5075 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
5076 info->bmiHeader.biWidth,
5077 info->bmiHeader.biHeight,
5078 info->bmiHeader.biBitCount );
5080 if (descr.compression == BI_BITFIELDS)
5082 *(DWORD *)info->bmiColors = descr.rMask;
5083 *((DWORD *)info->bmiColors+1) = descr.gMask;
5084 *((DWORD *)info->bmiColors+2) = descr.bMask;
5086 else
5088 /* if RLE or JPEG compression were supported,
5089 * this line would be invalid. */
5090 info->bmiHeader.biCompression = 0;
5093 done:
5094 GDI_ReleaseObj( dc->hPalette );
5095 GDI_ReleaseObj( hbitmap );
5096 return lines;
5099 /***********************************************************************
5100 * DIB_DoProtectDIBSection
5102 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
5104 DIBSECTION *dib = bmp->dib;
5105 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
5106 : -dib->dsBm.bmHeight;
5107 /* use the biSizeImage data as the memory size only if we're dealing with a
5108 compressed image where the value is set. Otherwise, calculate based on
5109 width * height */
5110 INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
5111 ? dib->dsBmih.biSizeImage
5112 : dib->dsBm.bmWidthBytes * effHeight;
5113 DWORD old_prot;
5115 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
5116 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
5119 /***********************************************************************
5120 * X11DRV_DIB_DoUpdateDIBSection
5122 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
5123 void *colorMap, int nColorMap,
5124 Drawable dest,
5125 DWORD xSrc, DWORD ySrc,
5126 DWORD xDest, DWORD yDest,
5127 DWORD width, DWORD height)
5129 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5130 X11DRV_DIB_IMAGEBITS_DESCR descr;
5132 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
5133 &descr.infoBpp, &descr.compression ) == -1)
5134 return;
5136 descr.physDev = NULL;
5137 descr.palentry = NULL;
5138 descr.image = dib->image;
5139 descr.colorMap = colorMap;
5140 descr.nColorMap = nColorMap;
5141 descr.bits = dib->dibSection.dsBm.bmBits;
5142 descr.depth = bmp->bitmap.bmBitsPixel;
5144 switch (descr.infoBpp)
5146 case 1:
5147 case 4:
5148 case 8:
5149 descr.rMask = descr.gMask = descr.bMask = 0;
5150 break;
5151 case 15:
5152 case 16:
5153 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
5154 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
5155 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
5156 break;
5158 case 24:
5159 case 32:
5160 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff0000;
5161 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x00ff00;
5162 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x0000ff;
5163 break;
5166 /* Hack for now */
5167 descr.drawable = dest;
5168 descr.gc = BITMAP_GC(bmp);
5169 descr.xSrc = xSrc;
5170 descr.ySrc = ySrc;
5171 descr.xDest = xDest;
5172 descr.yDest = yDest;
5173 descr.width = width;
5174 descr.height = height;
5175 #ifdef HAVE_LIBXXSHM
5176 descr.useShm = (dib->shminfo.shmid != -1);
5177 #else
5178 descr.useShm = FALSE;
5179 #endif
5180 descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
5182 if (toDIB)
5184 TRACE("Copying from Pixmap to DIB bits\n");
5185 X11DRV_DIB_GetImageBits( &descr );
5187 else
5189 TRACE("Copying from DIB bits to Pixmap\n");
5190 X11DRV_DIB_SetImageBits( &descr );
5194 /***********************************************************************
5195 * X11DRV_DIB_CopyDIBSection
5197 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
5198 DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
5199 DWORD width, DWORD height)
5201 BITMAPOBJ *bmp;
5202 DC *dcSrc = physDevSrc->dc;
5203 DC *dcDst = physDevDst->dc;
5204 int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
5206 TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", dcSrc, dcDst,
5207 xSrc, ySrc, xDest, yDest, width, height);
5208 /* this function is meant as an optimization for BitBlt,
5209 * not to be called otherwise */
5210 if (!(dcSrc->flags & DC_MEMORY)) {
5211 ERR("called for non-memory source DC!?\n");
5212 return;
5215 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
5216 if (!(bmp && bmp->dib)) {
5217 ERR("called for non-DIBSection!?\n");
5218 GDI_ReleaseObj( dcSrc->hBitmap );
5219 return;
5221 /* while BitBlt should already have made sure we only get
5222 * positive values, we should check for oversize values */
5223 if ((xSrc < bmp->bitmap.bmWidth) &&
5224 (ySrc < bmp->bitmap.bmHeight)) {
5225 if (xSrc + width > bmp->bitmap.bmWidth)
5226 width = bmp->bitmap.bmWidth - xSrc;
5227 if (ySrc + height > bmp->bitmap.bmHeight)
5228 height = bmp->bitmap.bmHeight - ySrc;
5229 /* if the source bitmap is 8bpp or less, we're supposed to use the
5230 * DC's palette for color conversion (not the DIB color table) */
5231 if (bmp->dib->dsBm.bmBitsPixel <= 8) {
5232 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5233 if ((!dcSrc->hPalette) ||
5234 (dcSrc->hPalette == GetStockObject(DEFAULT_PALETTE))) {
5235 /* HACK: no palette has been set in the source DC,
5236 * use the DIB colormap instead - this is necessary in some
5237 * cases since we need to do depth conversion in some places
5238 * where real Windows can just copy data straight over */
5239 colorMap = dib->colorMap;
5240 nColorMap = dib->nColorMap;
5241 } else {
5242 colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
5243 bmp->dib->dsBm.bmBitsPixel,
5244 (BITMAPINFO*)&(bmp->dib->dsBmih),
5245 &nColorMap );
5246 if (colorMap) aColorMap = TRUE;
5249 /* perform the copy */
5250 X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
5251 physDevDst->drawable, xSrc, ySrc,
5252 physDevDst->org.x + xDest, physDevDst->org.y + yDest,
5253 width, height);
5254 /* free color mapping */
5255 if (aColorMap)
5256 HeapFree(GetProcessHeap(), 0, colorMap);
5258 GDI_ReleaseObj( dcSrc->hBitmap );
5261 /***********************************************************************
5262 * X11DRV_DIB_DoUpdateDIBSection
5264 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
5266 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5267 X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
5268 (Drawable)bmp->physBitmap, 0, 0, 0, 0,
5269 bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
5272 /***********************************************************************
5273 * X11DRV_DIB_FaultHandler
5275 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
5277 BITMAPOBJ *bmp;
5278 INT state;
5280 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
5281 if (!bmp) return FALSE;
5283 state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
5284 if (state != DIB_Status_InSync) {
5285 /* no way to tell whether app needs read or write yet,
5286 * try read first */
5287 X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
5288 } else {
5289 /* hm, apparently the app must have write access */
5290 X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
5292 X11DRV_DIB_Unlock(bmp, TRUE);
5294 GDI_ReleaseObj( (HBITMAP)res );
5295 return TRUE;
5298 /***********************************************************************
5299 * X11DRV_DIB_Coerce
5301 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
5303 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5304 INT ret = DIB_Status_None;
5306 if (dib) {
5307 EnterCriticalSection(&(dib->lock));
5308 ret = dib->status;
5309 switch (req) {
5310 case DIB_Status_GdiMod:
5311 /* GDI access - request to draw on pixmap */
5312 switch (dib->status)
5314 default:
5315 case DIB_Status_None:
5316 dib->p_status = DIB_Status_GdiMod;
5317 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5318 break;
5320 case DIB_Status_GdiMod:
5321 TRACE("GdiMod requested in status GdiMod\n" );
5322 break;
5324 case DIB_Status_InSync:
5325 TRACE("GdiMod requested in status InSync\n" );
5326 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5327 dib->status = DIB_Status_GdiMod;
5328 dib->p_status = DIB_Status_InSync;
5329 break;
5331 case DIB_Status_AuxMod:
5332 TRACE("GdiMod requested in status AuxMod\n" );
5333 if (lossy) dib->status = DIB_Status_GdiMod;
5334 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
5335 dib->p_status = DIB_Status_AuxMod;
5336 if (dib->status != DIB_Status_AppMod) {
5337 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5338 break;
5340 /* fall through if copy_aux() had to change to AppMod state */
5342 case DIB_Status_AppMod:
5343 TRACE("GdiMod requested in status AppMod\n" );
5344 if (!lossy) {
5345 /* make it readonly to avoid app changing data while we copy */
5346 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5347 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5349 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5350 dib->p_status = DIB_Status_AppMod;
5351 dib->status = DIB_Status_GdiMod;
5352 break;
5354 break;
5356 case DIB_Status_InSync:
5357 /* App access - request access to read DIB surface */
5358 /* (typically called from signal handler) */
5359 switch (dib->status)
5361 default:
5362 case DIB_Status_None:
5363 /* shouldn't happen from signal handler */
5364 break;
5366 case DIB_Status_AuxMod:
5367 TRACE("InSync requested in status AuxMod\n" );
5368 if (lossy) dib->status = DIB_Status_InSync;
5369 else {
5370 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5371 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
5373 if (dib->status != DIB_Status_GdiMod) {
5374 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5375 break;
5377 /* fall through if copy_aux() had to change to GdiMod state */
5379 case DIB_Status_GdiMod:
5380 TRACE("InSync requested in status GdiMod\n" );
5381 if (!lossy) {
5382 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5383 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5385 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5386 dib->status = DIB_Status_InSync;
5387 break;
5389 case DIB_Status_InSync:
5390 TRACE("InSync requested in status InSync\n" );
5391 /* shouldn't happen from signal handler */
5392 break;
5394 case DIB_Status_AppMod:
5395 TRACE("InSync requested in status AppMod\n" );
5396 /* no reason to do anything here, and this
5397 * shouldn't happen from signal handler */
5398 break;
5400 break;
5402 case DIB_Status_AppMod:
5403 /* App access - request access to write DIB surface */
5404 /* (typically called from signal handler) */
5405 switch (dib->status)
5407 default:
5408 case DIB_Status_None:
5409 /* shouldn't happen from signal handler */
5410 break;
5412 case DIB_Status_AuxMod:
5413 TRACE("AppMod requested in status AuxMod\n" );
5414 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5415 if (lossy) dib->status = DIB_Status_AppMod;
5416 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5417 if (dib->status != DIB_Status_GdiMod)
5418 break;
5419 /* fall through if copy_aux() had to change to GdiMod state */
5421 case DIB_Status_GdiMod:
5422 TRACE("AppMod requested in status GdiMod\n" );
5423 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5424 if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5425 dib->status = DIB_Status_AppMod;
5426 break;
5428 case DIB_Status_InSync:
5429 TRACE("AppMod requested in status InSync\n" );
5430 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5431 dib->status = DIB_Status_AppMod;
5432 break;
5434 case DIB_Status_AppMod:
5435 TRACE("AppMod requested in status AppMod\n" );
5436 /* shouldn't happen from signal handler */
5437 break;
5439 break;
5441 case DIB_Status_AuxMod:
5442 if (dib->status == DIB_Status_None) {
5443 dib->p_status = req;
5444 } else {
5445 if (dib->status != DIB_Status_AuxMod)
5446 dib->p_status = dib->status;
5447 dib->status = DIB_Status_AuxMod;
5449 break;
5450 /* it is up to the caller to do the copy/conversion, probably
5451 * using the return value to decide where to copy from */
5453 LeaveCriticalSection(&(dib->lock));
5455 return ret;
5458 /***********************************************************************
5459 * X11DRV_DIB_Lock
5461 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
5463 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5464 INT ret = DIB_Status_None;
5466 if (dib) {
5467 TRACE("Locking %p from thread %08lx\n", bmp, GetCurrentThreadId());
5468 EnterCriticalSection(&(dib->lock));
5469 ret = dib->status;
5470 if (req != DIB_Status_None)
5471 X11DRV_DIB_Coerce(bmp, req, lossy);
5473 return ret;
5476 /***********************************************************************
5477 * X11DRV_DIB_Unlock
5479 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
5481 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5483 if (dib) {
5484 switch (dib->status)
5486 default:
5487 case DIB_Status_None:
5488 /* in case anyone is wondering, this is the "signal handler doesn't
5489 * work" case, where we always have to be ready for app access */
5490 if (commit) {
5491 switch (dib->p_status)
5493 case DIB_Status_AuxMod:
5494 TRACE("Unlocking and syncing from AuxMod\n" );
5495 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5496 if (dib->status != DIB_Status_None) {
5497 dib->p_status = dib->status;
5498 dib->status = DIB_Status_None;
5500 if (dib->p_status != DIB_Status_GdiMod)
5501 break;
5502 /* fall through if copy_aux() had to change to GdiMod state */
5504 case DIB_Status_GdiMod:
5505 TRACE("Unlocking and syncing from GdiMod\n" );
5506 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5507 break;
5509 default:
5510 TRACE("Unlocking without needing to sync\n" );
5511 break;
5514 else TRACE("Unlocking with no changes\n");
5515 dib->p_status = DIB_Status_None;
5516 break;
5518 case DIB_Status_GdiMod:
5519 TRACE("Unlocking in status GdiMod\n" );
5520 /* DIB was protected in Coerce */
5521 if (!commit) {
5522 /* no commit, revert to InSync if applicable */
5523 if ((dib->p_status == DIB_Status_InSync) ||
5524 (dib->p_status == DIB_Status_AppMod)) {
5525 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5526 dib->status = DIB_Status_InSync;
5529 break;
5531 case DIB_Status_InSync:
5532 TRACE("Unlocking in status InSync\n" );
5533 /* DIB was already protected in Coerce */
5534 break;
5536 case DIB_Status_AppMod:
5537 TRACE("Unlocking in status AppMod\n" );
5538 /* DIB was already protected in Coerce */
5539 /* this case is ordinary only called from the signal handler,
5540 * so we don't bother to check for !commit */
5541 break;
5543 case DIB_Status_AuxMod:
5544 TRACE("Unlocking in status AuxMod\n" );
5545 if (commit) {
5546 /* DIB may need protection now */
5547 if ((dib->p_status == DIB_Status_InSync) ||
5548 (dib->p_status == DIB_Status_AppMod))
5549 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5550 } else {
5551 /* no commit, revert to previous state */
5552 if (dib->p_status != DIB_Status_None)
5553 dib->status = dib->p_status;
5554 /* no protections changed */
5556 dib->p_status = DIB_Status_None;
5557 break;
5559 LeaveCriticalSection(&(dib->lock));
5560 TRACE("Unlocked %p\n", bmp);
5564 /***********************************************************************
5565 * X11DRV_CoerceDIBSection2
5567 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5569 BITMAPOBJ *bmp;
5570 INT ret;
5572 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5573 if (!bmp) return DIB_Status_None;
5574 ret = X11DRV_DIB_Coerce(bmp, req, lossy);
5575 GDI_ReleaseObj( hBmp );
5576 return ret;
5579 /***********************************************************************
5580 * X11DRV_LockDIBSection2
5582 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5584 BITMAPOBJ *bmp;
5585 INT ret;
5587 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5588 if (!bmp) return DIB_Status_None;
5589 ret = X11DRV_DIB_Lock(bmp, req, lossy);
5590 GDI_ReleaseObj( hBmp );
5591 return ret;
5594 /***********************************************************************
5595 * X11DRV_UnlockDIBSection2
5597 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
5599 BITMAPOBJ *bmp;
5601 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5602 if (!bmp) return;
5603 X11DRV_DIB_Unlock(bmp, commit);
5604 GDI_ReleaseObj( hBmp );
5607 /***********************************************************************
5608 * X11DRV_CoerceDIBSection
5610 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
5612 if (!physDev) return DIB_Status_None;
5613 return X11DRV_CoerceDIBSection2( physDev->dc->hBitmap, req, lossy );
5616 /***********************************************************************
5617 * X11DRV_LockDIBSection
5619 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
5621 if (!physDev) return DIB_Status_None;
5622 if (!(physDev->dc->flags & DC_MEMORY)) return DIB_Status_None;
5624 return X11DRV_LockDIBSection2( physDev->dc->hBitmap, req, lossy );
5627 /***********************************************************************
5628 * X11DRV_UnlockDIBSection
5630 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
5632 if (!physDev) return;
5633 if (!(physDev->dc->flags & DC_MEMORY)) return;
5635 X11DRV_UnlockDIBSection2( physDev->dc->hBitmap, commit );
5639 #ifdef HAVE_LIBXXSHM
5640 /***********************************************************************
5641 * X11DRV_XShmErrorHandler
5644 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
5646 return 1; /* FIXME: should check event contents */
5649 /***********************************************************************
5650 * X11DRV_XShmCreateImage
5653 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
5654 XShmSegmentInfo* shminfo)
5656 XImage *image;
5658 image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
5659 if (image)
5661 shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
5662 IPC_CREAT|0700);
5663 if( shminfo->shmid != -1 )
5665 shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
5666 if( shminfo->shmaddr != (char*)-1 )
5668 BOOL ok;
5670 shminfo->readOnly = FALSE;
5671 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
5672 ok = (XShmAttach( gdi_display, shminfo ) != 0);
5673 if (X11DRV_check_error()) ok = FALSE;
5674 if (ok)
5676 shmctl(shminfo->shmid, IPC_RMID, 0);
5677 return image; /* Success! */
5679 /* An error occured */
5680 shmdt(shminfo->shmaddr);
5682 shmctl(shminfo->shmid, IPC_RMID, 0);
5684 XFlush(gdi_display);
5685 XDestroyImage(image);
5686 image = NULL;
5688 return image;
5690 #endif /* HAVE_LIBXXSHM */
5693 /***********************************************************************
5694 * X11DRV_DIB_CreateDIBSection
5696 HBITMAP X11DRV_DIB_CreateDIBSection(
5697 X11DRV_PDEVICE *physDev, BITMAPINFO *bmi, UINT usage,
5698 LPVOID *bits, HANDLE section,
5699 DWORD offset, DWORD ovr_pitch)
5701 HBITMAP res = 0;
5702 BITMAPOBJ *bmp = NULL;
5703 X11DRV_DIBSECTION *dib = NULL;
5704 int *colorMap = NULL;
5705 int nColorMap;
5707 /* Fill BITMAP32 structure with DIB data */
5708 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
5709 INT effHeight, totalSize;
5710 BITMAP bm;
5711 LPVOID mapBits = NULL;
5713 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
5714 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
5715 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
5717 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
5718 bm.bmType = 0;
5719 bm.bmWidth = bi->biWidth;
5720 bm.bmHeight = effHeight;
5721 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
5722 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
5723 bm.bmPlanes = bi->biPlanes;
5724 bm.bmBitsPixel = bi->biBitCount;
5725 bm.bmBits = NULL;
5727 /* Get storage location for DIB bits. Only use biSizeImage if it's valid and
5728 we're dealing with a compressed bitmap. Otherwise, use width * height. */
5729 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
5730 ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
5732 if (section)
5734 SYSTEM_INFO SystemInfo;
5735 DWORD mapOffset;
5736 INT mapSize;
5738 GetSystemInfo( &SystemInfo );
5739 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
5740 mapSize = totalSize + (offset - mapOffset);
5741 mapBits = MapViewOfFile( section,
5742 FILE_MAP_ALL_ACCESS,
5744 mapOffset,
5745 mapSize );
5746 bm.bmBits = (char *)mapBits + (offset - mapOffset);
5748 else if (ovr_pitch && offset)
5749 bm.bmBits = (LPVOID) offset;
5750 else {
5751 offset = 0;
5752 bm.bmBits = VirtualAlloc(NULL, totalSize,
5753 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
5756 /* Create Color Map */
5757 if (bm.bmBits && bm.bmBitsPixel <= 8)
5758 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? physDev : NULL,
5759 usage, bm.bmBitsPixel, bmi, &nColorMap );
5761 /* Allocate Memory for DIB and fill structure */
5762 if (bm.bmBits)
5763 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
5764 if (dib)
5766 dib->dibSection.dsBm = bm;
5767 dib->dibSection.dsBmih = *bi;
5768 dib->dibSection.dsBmih.biSizeImage = totalSize;
5770 /* Set dsBitfields values */
5771 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
5773 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
5775 else switch( bi->biBitCount )
5777 case 15:
5778 case 16:
5779 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
5780 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
5781 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
5782 break;
5784 case 24:
5785 case 32:
5786 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff0000;
5787 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
5788 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
5789 break;
5791 dib->dibSection.dshSection = section;
5792 dib->dibSection.dsOffset = offset;
5794 dib->status = DIB_Status_None;
5795 dib->nColorMap = nColorMap;
5796 dib->colorMap = colorMap;
5799 /* Create Device Dependent Bitmap and add DIB pointer */
5800 if (dib)
5802 res = CreateDIBitmap(physDev->hdc, bi, 0, NULL, bmi, usage);
5803 if (res)
5805 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
5806 if (bmp) bmp->dib = (DIBSECTION *) dib;
5810 /* Create XImage */
5811 if (dib && bmp)
5813 wine_tsx11_lock();
5814 #ifdef HAVE_LIBXXSHM
5815 if (XShmQueryExtension(gdi_display) &&
5816 (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
5817 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
5819 ; /* Created Image */
5820 } else {
5821 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5822 dib->shminfo.shmid = -1;
5824 #else
5825 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5826 #endif
5827 wine_tsx11_unlock();
5830 /* Clean up in case of errors */
5831 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
5833 TRACE("got an error res=%p, bmp=%p, dib=%p, bm.bmBits=%p\n",
5834 res, bmp, dib, bm.bmBits);
5835 if (bm.bmBits)
5837 if (section)
5838 UnmapViewOfFile(mapBits), bm.bmBits = NULL;
5839 else if (!offset)
5840 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
5843 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
5844 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
5845 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
5846 if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
5847 if (res) { DeleteObject(res); res = 0; }
5849 else if (bm.bmBits)
5851 /* Install fault handler, if possible */
5852 InitializeCriticalSection(&(dib->lock));
5853 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
5855 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5856 if (dib) dib->status = DIB_Status_AppMod;
5860 /* Return BITMAP handle and storage location */
5861 if (bmp) GDI_ReleaseObj(res);
5862 if (bm.bmBits && bits) *bits = bm.bmBits;
5863 return res;
5866 /***********************************************************************
5867 * X11DRV_DIB_DeleteDIBSection
5869 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
5871 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5873 if (dib->image)
5875 wine_tsx11_lock();
5876 #ifdef HAVE_LIBXXSHM
5877 if (dib->shminfo.shmid != -1)
5879 XShmDetach (gdi_display, &(dib->shminfo));
5880 XDestroyImage (dib->image);
5881 shmdt (dib->shminfo.shmaddr);
5882 dib->shminfo.shmid = -1;
5884 else
5885 #endif
5886 XDestroyImage( dib->image );
5887 wine_tsx11_unlock();
5890 if (dib->colorMap)
5891 HeapFree(GetProcessHeap(), 0, dib->colorMap);
5893 DeleteCriticalSection(&(dib->lock));
5896 /***********************************************************************
5897 * SetDIBColorTable (X11DRV.@)
5899 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
5901 BITMAPOBJ * bmp;
5902 X11DRV_DIBSECTION *dib;
5903 UINT ret = 0;
5905 if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
5906 dib = (X11DRV_DIBSECTION *) bmp->dib;
5908 if (dib && dib->colorMap) {
5909 UINT end = count + start;
5910 if (end > dib->nColorMap) end = dib->nColorMap;
5912 * Changing color table might change the mapping between
5913 * DIB colors and X11 colors and thus alter the visible state
5914 * of the bitmap object.
5916 X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
5917 X11DRV_DIB_GenColorMap( physDev, dib->colorMap, DIB_RGB_COLORS,
5918 dib->dibSection.dsBm.bmBitsPixel,
5919 TRUE, colors, start, end );
5920 X11DRV_DIB_Unlock(bmp, TRUE);
5921 ret = end - start;
5923 GDI_ReleaseObj( physDev->dc->hBitmap );
5924 return ret;
5927 /***********************************************************************
5928 * GetDIBColorTable (X11DRV.@)
5930 UINT X11DRV_GetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, RGBQUAD *colors )
5932 BITMAPOBJ * bmp;
5933 X11DRV_DIBSECTION *dib;
5934 UINT ret = 0;
5936 if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
5937 dib = (X11DRV_DIBSECTION *) bmp->dib;
5939 if (dib && dib->colorMap) {
5940 UINT i, end = count + start;
5941 if (end > dib->nColorMap) end = dib->nColorMap;
5942 for (i = start; i < end; i++,colors++) {
5943 COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
5944 colors->rgbBlue = GetBValue(col);
5945 colors->rgbGreen = GetGValue(col);
5946 colors->rgbRed = GetRValue(col);
5947 colors->rgbReserved = 0;
5949 ret = end-start;
5951 GDI_ReleaseObj( physDev->dc->hBitmap );
5952 return ret;
5956 /**************************************************************************
5957 * X11DRV_DIB_CreateDIBFromPixmap
5959 * Allocates a packed DIB and copies the Pixmap data into it.
5960 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
5962 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
5964 HBITMAP hBmp = 0;
5965 BITMAPOBJ *pBmp = NULL;
5966 HGLOBAL hPackedDIB = 0;
5968 /* Allocates an HBITMAP which references the Pixmap passed to us */
5969 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
5970 if (!hBmp)
5972 TRACE("\tCould not create bitmap header for Pixmap\n");
5973 goto END;
5977 * Create a packed DIB from the Pixmap wrapper bitmap created above.
5978 * A packed DIB contains a BITMAPINFO structure followed immediately by
5979 * an optional color palette and the pixel data.
5981 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
5983 /* Get a pointer to the BITMAPOBJ structure */
5984 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5986 /* We can now get rid of the HBITMAP wrapper we created earlier.
5987 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
5989 if (!bDeletePixmap)
5991 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
5992 pBmp->physBitmap = NULL;
5993 pBmp->funcs = NULL;
5995 GDI_ReleaseObj( hBmp );
5996 DeleteObject(hBmp);
5998 END:
5999 TRACE("\tReturning packed DIB %p\n", hPackedDIB);
6000 return hPackedDIB;
6004 /**************************************************************************
6005 * X11DRV_DIB_CreatePixmapFromDIB
6007 * Creates a Pixmap from a packed DIB
6009 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
6011 Pixmap pixmap = None;
6012 HBITMAP hBmp = 0;
6013 BITMAPOBJ *pBmp = NULL;
6014 LPBYTE pPackedDIB = NULL;
6015 LPBITMAPINFO pbmi = NULL;
6016 LPBITMAPINFOHEADER pbmiHeader = NULL;
6017 LPBYTE pbits = NULL;
6019 /* Get a pointer to the packed DIB's data */
6020 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
6021 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
6022 pbmi = (LPBITMAPINFO)pPackedDIB;
6023 pbits = (LPBYTE)(pPackedDIB
6024 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
6026 /* Create a DDB from the DIB */
6028 hBmp = CreateDIBitmap(hdc,
6029 pbmiHeader,
6030 CBM_INIT,
6031 (LPVOID)pbits,
6032 pbmi,
6033 DIB_RGB_COLORS);
6035 GlobalUnlock(hPackedDIB);
6037 TRACE("CreateDIBitmap returned %p\n", hBmp);
6039 /* Retrieve the internal Pixmap from the DDB */
6041 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
6043 pixmap = (Pixmap)pBmp->physBitmap;
6044 /* clear the physBitmap so that we can steal its pixmap */
6045 pBmp->physBitmap = NULL;
6046 pBmp->funcs = NULL;
6048 /* Delete the DDB we created earlier now that we have stolen its pixmap */
6049 GDI_ReleaseObj( hBmp );
6050 DeleteObject(hBmp);
6052 TRACE("\tReturning Pixmap %ld\n", pixmap);
6053 return pixmap;