Authors: Robert Dickenson <robd@reactos.org>, Steven Edwards <Steven_Ed4153@yahoo...
[wine/multimedia.git] / graphics / x11drv / dib.c
blob4a3db4808834243862761c7bb225bdea35d9aec3
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 if (dstwidth % 8){
1632 srcval=*srcbyte;
1633 switch (dstwidth & 7)
1635 case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1636 case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1637 case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1638 case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1639 case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1640 case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1641 case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
1644 srcbits += linebytes;
1648 /***********************************************************************
1649 * X11DRV_DIB_GetImageBits_1
1651 * GetDIBits for a 1-bit deep DIB.
1653 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
1654 DWORD dstwidth, DWORD srcwidth,
1655 RGBQUAD *colors, PALETTEENTRY *srccolors,
1656 XImage *bmpImage, DWORD linebytes )
1658 DWORD x;
1659 int h;
1661 if (lines < 0 ) {
1662 lines = -lines;
1663 dstbits = dstbits + linebytes * (lines - 1);
1664 linebytes = -linebytes;
1667 switch (bmpImage->depth)
1669 case 1:
1670 case 4:
1671 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1672 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
1673 BYTE* dstbyte;
1675 for (h=lines-1; h>=0; h--) {
1676 BYTE dstval;
1677 dstbyte=dstbits;
1678 dstval=0;
1679 for (x=0; x<dstwidth; x++) {
1680 PALETTEENTRY srcval;
1681 srcval=srccolors[XGetPixel(bmpImage, x, h)];
1682 dstval|=(X11DRV_DIB_GetNearestIndex
1683 (colors, 2,
1684 srcval.peRed,
1685 srcval.peGreen,
1686 srcval.peBlue) << (7 - (x & 7)));
1687 if ((x&7)==7) {
1688 *dstbyte++=dstval;
1689 dstval=0;
1692 if ((dstwidth&7)!=0) {
1693 *dstbyte=dstval;
1695 dstbits += linebytes;
1697 } else {
1698 goto notsupported;
1700 break;
1702 case 8:
1703 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1704 /* ==== pal 8 bmp -> pal 1 dib ==== */
1705 const void* srcbits;
1706 const BYTE* srcpixel;
1707 BYTE* dstbyte;
1709 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1711 for (h=0; h<lines; h++) {
1712 BYTE dstval;
1713 srcpixel=srcbits;
1714 dstbyte=dstbits;
1715 dstval=0;
1716 for (x=0; x<dstwidth; x++) {
1717 PALETTEENTRY srcval;
1718 srcval=srccolors[(int)*srcpixel++];
1719 dstval|=(X11DRV_DIB_GetNearestIndex
1720 (colors, 2,
1721 srcval.peRed,
1722 srcval.peGreen,
1723 srcval.peBlue) << (7-(x&7)) );
1724 if ((x&7)==7) {
1725 *dstbyte++=dstval;
1726 dstval=0;
1729 if ((dstwidth&7)!=0) {
1730 *dstbyte=dstval;
1732 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1733 dstbits += linebytes;
1735 } else {
1736 goto notsupported;
1738 break;
1740 case 15:
1741 case 16:
1743 const void* srcbits;
1744 const WORD* srcpixel;
1745 BYTE* dstbyte;
1747 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1749 if (bmpImage->green_mask==0x03e0) {
1750 if (bmpImage->red_mask==0x7c00) {
1751 /* ==== rgb 555 bmp -> pal 1 dib ==== */
1752 for (h=0; h<lines; h++) {
1753 BYTE dstval;
1754 srcpixel=srcbits;
1755 dstbyte=dstbits;
1756 dstval=0;
1757 for (x=0; x<dstwidth; x++) {
1758 WORD srcval;
1759 srcval=*srcpixel++;
1760 dstval|=(X11DRV_DIB_GetNearestIndex
1761 (colors, 2,
1762 ((srcval >> 7) & 0xf8) | /* r */
1763 ((srcval >> 12) & 0x07),
1764 ((srcval >> 2) & 0xf8) | /* g */
1765 ((srcval >> 7) & 0x07),
1766 ((srcval << 3) & 0xf8) | /* b */
1767 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
1768 if ((x&7)==7) {
1769 *dstbyte++=dstval;
1770 dstval=0;
1773 if ((dstwidth&7)!=0) {
1774 *dstbyte=dstval;
1776 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1777 dstbits += linebytes;
1779 } else if (bmpImage->blue_mask==0x7c00) {
1780 /* ==== bgr 555 bmp -> pal 1 dib ==== */
1781 for (h=0; h<lines; h++) {
1782 WORD dstval;
1783 srcpixel=srcbits;
1784 dstbyte=dstbits;
1785 dstval=0;
1786 for (x=0; x<dstwidth; x++) {
1787 BYTE srcval;
1788 srcval=*srcpixel++;
1789 dstval|=(X11DRV_DIB_GetNearestIndex
1790 (colors, 2,
1791 ((srcval << 3) & 0xf8) | /* r */
1792 ((srcval >> 2) & 0x07),
1793 ((srcval >> 2) & 0xf8) | /* g */
1794 ((srcval >> 7) & 0x07),
1795 ((srcval >> 7) & 0xf8) | /* b */
1796 ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
1797 if ((x&7)==7) {
1798 *dstbyte++=dstval;
1799 dstval=0;
1802 if ((dstwidth&7)!=0) {
1803 *dstbyte=dstval;
1805 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1806 dstbits += linebytes;
1808 } else {
1809 goto notsupported;
1811 } else if (bmpImage->green_mask==0x07e0) {
1812 if (bmpImage->red_mask==0xf800) {
1813 /* ==== rgb 565 bmp -> pal 1 dib ==== */
1814 for (h=0; h<lines; h++) {
1815 BYTE dstval;
1816 srcpixel=srcbits;
1817 dstbyte=dstbits;
1818 dstval=0;
1819 for (x=0; x<dstwidth; x++) {
1820 WORD srcval;
1821 srcval=*srcpixel++;
1822 dstval|=(X11DRV_DIB_GetNearestIndex
1823 (colors, 2,
1824 ((srcval >> 8) & 0xf8) | /* r */
1825 ((srcval >> 13) & 0x07),
1826 ((srcval >> 3) & 0xfc) | /* g */
1827 ((srcval >> 9) & 0x03),
1828 ((srcval << 3) & 0xf8) | /* b */
1829 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
1830 if ((x&7)==7) {
1831 *dstbyte++=dstval;
1832 dstval=0;
1835 if ((dstwidth&7)!=0) {
1836 *dstbyte=dstval;
1838 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1839 dstbits += linebytes;
1841 } else if (bmpImage->blue_mask==0xf800) {
1842 /* ==== bgr 565 bmp -> pal 1 dib ==== */
1843 for (h=0; h<lines; h++) {
1844 BYTE dstval;
1845 srcpixel=srcbits;
1846 dstbyte=dstbits;
1847 dstval=0;
1848 for (x=0; x<dstwidth; x++) {
1849 WORD srcval;
1850 srcval=*srcpixel++;
1851 dstval|=(X11DRV_DIB_GetNearestIndex
1852 (colors, 2,
1853 ((srcval << 3) & 0xf8) | /* r */
1854 ((srcval >> 2) & 0x07),
1855 ((srcval >> 3) & 0xfc) | /* g */
1856 ((srcval >> 9) & 0x03),
1857 ((srcval >> 8) & 0xf8) | /* b */
1858 ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
1859 if ((x&7)==7) {
1860 *dstbyte++=dstval;
1861 dstval=0;
1864 if ((dstwidth&7)!=0) {
1865 *dstbyte=dstval;
1867 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1868 dstbits += linebytes;
1870 } else {
1871 goto notsupported;
1873 } else {
1874 goto notsupported;
1877 break;
1879 case 24:
1880 case 32:
1882 const void* srcbits;
1883 const BYTE *srcbyte;
1884 BYTE* dstbyte;
1885 int bytes_per_pixel;
1887 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1888 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1890 if (bmpImage->green_mask!=0x00ff00 ||
1891 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1892 goto notsupported;
1893 } else if (bmpImage->blue_mask==0xff) {
1894 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
1895 for (h=0; h<lines; h++) {
1896 BYTE dstval;
1897 srcbyte=srcbits;
1898 dstbyte=dstbits;
1899 dstval=0;
1900 for (x=0; x<dstwidth; x++) {
1901 dstval|=(X11DRV_DIB_GetNearestIndex
1902 (colors, 2,
1903 srcbyte[2],
1904 srcbyte[1],
1905 srcbyte[0]) << (7-(x&7)) );
1906 srcbyte+=bytes_per_pixel;
1907 if ((x&7)==7) {
1908 *dstbyte++=dstval;
1909 dstval=0;
1912 if ((dstwidth&7)!=0) {
1913 *dstbyte=dstval;
1915 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1916 dstbits += linebytes;
1918 } else {
1919 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
1920 for (h=0; h<lines; h++) {
1921 BYTE dstval;
1922 srcbyte=srcbits;
1923 dstbyte=dstbits;
1924 dstval=0;
1925 for (x=0; x<dstwidth; x++) {
1926 dstval|=(X11DRV_DIB_GetNearestIndex
1927 (colors, 2,
1928 srcbyte[0],
1929 srcbyte[1],
1930 srcbyte[2]) << (7-(x&7)) );
1931 srcbyte+=bytes_per_pixel;
1932 if ((x&7)==7) {
1933 *dstbyte++=dstval;
1934 dstval=0;
1937 if ((dstwidth&7)!=0) {
1938 *dstbyte=dstval;
1940 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1941 dstbits += linebytes;
1945 break;
1947 default:
1948 notsupported:
1950 BYTE* dstbyte;
1951 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
1953 /* ==== any bmp format -> pal 1 dib ==== */
1954 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
1955 bmpImage->bits_per_pixel, bmpImage->red_mask,
1956 bmpImage->green_mask, bmpImage->blue_mask );
1958 for (h=lines-1; h>=0; h--) {
1959 BYTE dstval;
1960 dstbyte=dstbits;
1961 dstval=0;
1962 for (x=0; x<dstwidth; x++) {
1963 dstval|=(XGetPixel( bmpImage, x, h) >= white) << (7 - (x&7));
1964 if ((x&7)==7) {
1965 *dstbyte++=dstval;
1966 dstval=0;
1969 if ((dstwidth&7)!=0) {
1970 *dstbyte=dstval;
1972 dstbits += linebytes;
1975 break;
1979 /***********************************************************************
1980 * X11DRV_DIB_SetImageBits_4
1982 * SetDIBits for a 4-bit deep DIB.
1984 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
1985 DWORD srcwidth, DWORD dstwidth, int left,
1986 int *colors, XImage *bmpImage, DWORD linebytes)
1988 int h;
1989 const BYTE* srcbyte;
1990 DWORD i, x;
1992 if (lines < 0 ) {
1993 lines = -lines;
1994 srcbits = srcbits + linebytes * (lines - 1);
1995 linebytes = -linebytes;
1998 if (left & 1) {
1999 left--;
2000 dstwidth++;
2002 srcbits += left >> 1;
2004 /* ==== pal 4 dib -> any bmp format ==== */
2005 for (h = lines-1; h >= 0; h--) {
2006 srcbyte=srcbits;
2007 for (i = dstwidth/2, x = left; i > 0; i--) {
2008 BYTE srcval=*srcbyte++;
2009 XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
2010 XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
2012 if (dstwidth & 1)
2013 XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
2014 srcbits += linebytes;
2020 /***********************************************************************
2021 * X11DRV_DIB_GetImageBits_4
2023 * GetDIBits for a 4-bit deep DIB.
2025 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
2026 DWORD srcwidth, DWORD dstwidth,
2027 RGBQUAD *colors, PALETTEENTRY *srccolors,
2028 XImage *bmpImage, DWORD linebytes )
2030 DWORD x;
2031 int h;
2032 BYTE *bits;
2034 if (lines < 0 )
2036 lines = -lines;
2037 dstbits = dstbits + ( linebytes * (lines-1) );
2038 linebytes = -linebytes;
2041 bits = dstbits;
2043 switch (bmpImage->depth) {
2044 case 1:
2045 case 4:
2046 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2047 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
2048 BYTE* dstbyte;
2050 for (h = lines-1; h >= 0; h--) {
2051 BYTE dstval;
2052 dstbyte=dstbits;
2053 dstval=0;
2054 for (x = 0; x < dstwidth; x++) {
2055 PALETTEENTRY srcval;
2056 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2057 dstval|=(X11DRV_DIB_GetNearestIndex
2058 (colors, 16,
2059 srcval.peRed,
2060 srcval.peGreen,
2061 srcval.peBlue) << (4-((x&1)<<2)));
2062 if ((x&1)==1) {
2063 *dstbyte++=dstval;
2064 dstval=0;
2067 if ((dstwidth&1)!=0) {
2068 *dstbyte=dstval;
2070 dstbits += linebytes;
2072 } else {
2073 goto notsupported;
2075 break;
2077 case 8:
2078 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2079 /* ==== pal 8 bmp -> pal 4 dib ==== */
2080 const void* srcbits;
2081 const BYTE *srcpixel;
2082 BYTE* dstbyte;
2084 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2085 for (h=0; h<lines; h++) {
2086 BYTE dstval;
2087 srcpixel=srcbits;
2088 dstbyte=dstbits;
2089 dstval=0;
2090 for (x=0; x<dstwidth; x++) {
2091 PALETTEENTRY srcval;
2092 srcval = srccolors[(int)*srcpixel++];
2093 dstval|=(X11DRV_DIB_GetNearestIndex
2094 (colors, 16,
2095 srcval.peRed,
2096 srcval.peGreen,
2097 srcval.peBlue) << (4*(1-(x&1))) );
2098 if ((x&1)==1) {
2099 *dstbyte++=dstval;
2100 dstval=0;
2103 if ((dstwidth&1)!=0) {
2104 *dstbyte=dstval;
2106 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2107 dstbits += linebytes;
2109 } else {
2110 goto notsupported;
2112 break;
2114 case 15:
2115 case 16:
2117 const void* srcbits;
2118 const WORD* srcpixel;
2119 BYTE* dstbyte;
2121 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2123 if (bmpImage->green_mask==0x03e0) {
2124 if (bmpImage->red_mask==0x7c00) {
2125 /* ==== rgb 555 bmp -> pal 4 dib ==== */
2126 for (h=0; h<lines; h++) {
2127 BYTE dstval;
2128 srcpixel=srcbits;
2129 dstbyte=dstbits;
2130 dstval=0;
2131 for (x=0; x<dstwidth; x++) {
2132 WORD srcval;
2133 srcval=*srcpixel++;
2134 dstval|=(X11DRV_DIB_GetNearestIndex
2135 (colors, 16,
2136 ((srcval >> 7) & 0xf8) | /* r */
2137 ((srcval >> 12) & 0x07),
2138 ((srcval >> 2) & 0xf8) | /* g */
2139 ((srcval >> 7) & 0x07),
2140 ((srcval << 3) & 0xf8) | /* b */
2141 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
2142 if ((x&1)==1) {
2143 *dstbyte++=dstval;
2144 dstval=0;
2147 if ((dstwidth&1)!=0) {
2148 *dstbyte=dstval;
2150 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2151 dstbits += linebytes;
2153 } else if (bmpImage->blue_mask==0x7c00) {
2154 /* ==== bgr 555 bmp -> pal 4 dib ==== */
2155 for (h=0; h<lines; h++) {
2156 WORD dstval;
2157 srcpixel=srcbits;
2158 dstbyte=dstbits;
2159 dstval=0;
2160 for (x=0; x<dstwidth; x++) {
2161 WORD srcval;
2162 srcval=*srcpixel++;
2163 dstval|=(X11DRV_DIB_GetNearestIndex
2164 (colors, 16,
2165 ((srcval << 3) & 0xf8) | /* r */
2166 ((srcval >> 2) & 0x07),
2167 ((srcval >> 2) & 0xf8) | /* g */
2168 ((srcval >> 7) & 0x07),
2169 ((srcval >> 7) & 0xf8) | /* b */
2170 ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
2171 if ((x&1)==1) {
2172 *dstbyte++=dstval;
2173 dstval=0;
2176 if ((dstwidth&1)!=0) {
2177 *dstbyte=dstval;
2179 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2180 dstbits += linebytes;
2182 } else {
2183 goto notsupported;
2185 } else if (bmpImage->green_mask==0x07e0) {
2186 if (bmpImage->red_mask==0xf800) {
2187 /* ==== rgb 565 bmp -> pal 4 dib ==== */
2188 for (h=0; h<lines; h++) {
2189 BYTE dstval;
2190 srcpixel=srcbits;
2191 dstbyte=dstbits;
2192 dstval=0;
2193 for (x=0; x<dstwidth; x++) {
2194 WORD srcval;
2195 srcval=*srcpixel++;
2196 dstval|=(X11DRV_DIB_GetNearestIndex
2197 (colors, 16,
2198 ((srcval >> 8) & 0xf8) | /* r */
2199 ((srcval >> 13) & 0x07),
2200 ((srcval >> 3) & 0xfc) | /* g */
2201 ((srcval >> 9) & 0x03),
2202 ((srcval << 3) & 0xf8) | /* b */
2203 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
2204 if ((x&1)==1) {
2205 *dstbyte++=dstval;
2206 dstval=0;
2209 if ((dstwidth&1)!=0) {
2210 *dstbyte=dstval;
2212 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2213 dstbits += linebytes;
2215 } else if (bmpImage->blue_mask==0xf800) {
2216 /* ==== bgr 565 bmp -> pal 4 dib ==== */
2217 for (h=0; h<lines; h++) {
2218 WORD dstval;
2219 srcpixel=srcbits;
2220 dstbyte=dstbits;
2221 dstval=0;
2222 for (x=0; x<dstwidth; x++) {
2223 WORD srcval;
2224 srcval=*srcpixel++;
2225 dstval|=(X11DRV_DIB_GetNearestIndex
2226 (colors, 16,
2227 ((srcval << 3) & 0xf8) | /* r */
2228 ((srcval >> 2) & 0x07),
2229 ((srcval >> 3) & 0xfc) | /* g */
2230 ((srcval >> 9) & 0x03),
2231 ((srcval >> 8) & 0xf8) | /* b */
2232 ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
2233 if ((x&1)==1) {
2234 *dstbyte++=dstval;
2235 dstval=0;
2238 if ((dstwidth&1)!=0) {
2239 *dstbyte=dstval;
2241 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2242 dstbits += linebytes;
2244 } else {
2245 goto notsupported;
2247 } else {
2248 goto notsupported;
2251 break;
2253 case 24:
2254 if (bmpImage->bits_per_pixel==24) {
2255 const void* srcbits;
2256 const BYTE *srcbyte;
2257 BYTE* dstbyte;
2259 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2261 if (bmpImage->green_mask!=0x00ff00 ||
2262 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2263 goto notsupported;
2264 } else if (bmpImage->blue_mask==0xff) {
2265 /* ==== rgb 888 bmp -> pal 4 dib ==== */
2266 for (h=0; h<lines; h++) {
2267 srcbyte=srcbits;
2268 dstbyte=dstbits;
2269 for (x=0; x<dstwidth/2; x++) {
2270 /* Do 2 pixels at a time */
2271 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2272 (colors, 16,
2273 srcbyte[2],
2274 srcbyte[1],
2275 srcbyte[0]) << 4) |
2276 X11DRV_DIB_GetNearestIndex
2277 (colors, 16,
2278 srcbyte[5],
2279 srcbyte[4],
2280 srcbyte[3]);
2281 srcbyte+=6;
2283 if (dstwidth&1) {
2284 /* And the the odd pixel */
2285 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2286 (colors, 16,
2287 srcbyte[2],
2288 srcbyte[1],
2289 srcbyte[0]) << 4);
2291 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2292 dstbits += linebytes;
2294 } else {
2295 /* ==== bgr 888 bmp -> pal 4 dib ==== */
2296 for (h=0; h<lines; h++) {
2297 srcbyte=srcbits;
2298 dstbyte=dstbits;
2299 for (x=0; x<dstwidth/2; x++) {
2300 /* Do 2 pixels at a time */
2301 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2302 (colors, 16,
2303 srcbyte[0],
2304 srcbyte[1],
2305 srcbyte[2]) << 4) |
2306 X11DRV_DIB_GetNearestIndex
2307 (colors, 16,
2308 srcbyte[3],
2309 srcbyte[4],
2310 srcbyte[5]);
2311 srcbyte+=6;
2313 if (dstwidth&1) {
2314 /* And the the odd pixel */
2315 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2316 (colors, 16,
2317 srcbyte[0],
2318 srcbyte[1],
2319 srcbyte[2]) << 4);
2321 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2322 dstbits += linebytes;
2325 break;
2327 /* Fall through */
2329 case 32:
2331 const void* srcbits;
2332 const BYTE *srcbyte;
2333 BYTE* dstbyte;
2335 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2337 if (bmpImage->green_mask!=0x00ff00 ||
2338 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2339 goto notsupported;
2340 } else if (bmpImage->blue_mask==0xff) {
2341 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
2342 for (h=0; h<lines; h++) {
2343 srcbyte=srcbits;
2344 dstbyte=dstbits;
2345 for (x=0; x<dstwidth/2; x++) {
2346 /* Do 2 pixels at a time */
2347 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2348 (colors, 16,
2349 srcbyte[2],
2350 srcbyte[1],
2351 srcbyte[0]) << 4) |
2352 X11DRV_DIB_GetNearestIndex
2353 (colors, 16,
2354 srcbyte[6],
2355 srcbyte[5],
2356 srcbyte[4]);
2357 srcbyte+=8;
2359 if (dstwidth&1) {
2360 /* And the the odd pixel */
2361 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2362 (colors, 16,
2363 srcbyte[2],
2364 srcbyte[1],
2365 srcbyte[0]) << 4);
2367 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2368 dstbits += linebytes;
2370 } else {
2371 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
2372 for (h=0; h<lines; h++) {
2373 srcbyte=srcbits;
2374 dstbyte=dstbits;
2375 for (x=0; x<dstwidth/2; x++) {
2376 /* Do 2 pixels at a time */
2377 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2378 (colors, 16,
2379 srcbyte[0],
2380 srcbyte[1],
2381 srcbyte[2]) << 4) |
2382 X11DRV_DIB_GetNearestIndex
2383 (colors, 16,
2384 srcbyte[4],
2385 srcbyte[5],
2386 srcbyte[6]);
2387 srcbyte+=8;
2389 if (dstwidth&1) {
2390 /* And the the odd pixel */
2391 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2392 (colors, 16,
2393 srcbyte[0],
2394 srcbyte[1],
2395 srcbyte[2]) << 4);
2397 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2398 dstbits += linebytes;
2402 break;
2404 default:
2405 notsupported:
2407 BYTE* dstbyte;
2409 /* ==== any bmp format -> pal 4 dib ==== */
2410 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
2411 bmpImage->bits_per_pixel, bmpImage->red_mask,
2412 bmpImage->green_mask, bmpImage->blue_mask );
2413 for (h=lines-1; h>=0; h--) {
2414 dstbyte=dstbits;
2415 for (x=0; x<(dstwidth & ~1); x+=2) {
2416 *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
2417 X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
2419 if (dstwidth & 1) {
2420 *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
2422 dstbits += linebytes;
2425 break;
2429 /***********************************************************************
2430 * X11DRV_DIB_SetImageBits_RLE4
2432 * SetDIBits for a 4-bit deep compressed DIB.
2434 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
2435 DWORD width, DWORD dstwidth,
2436 int left, int *colors,
2437 XImage *bmpImage )
2439 int x = 0, y = lines - 1, c, length;
2440 const BYTE *begin = bits;
2442 while (y >= 0)
2444 length = *bits++;
2445 if (length) { /* encoded */
2446 c = *bits++;
2447 while (length--) {
2448 if (x >= width) break;
2449 XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2450 if (!length--) break;
2451 if (x >= width) break;
2452 XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2454 } else {
2455 length = *bits++;
2456 switch (length)
2458 case RLE_EOL:
2459 x = 0;
2460 y--;
2461 break;
2463 case RLE_END:
2464 return;
2466 case RLE_DELTA:
2467 x += *bits++;
2468 y -= *bits++;
2469 break;
2471 default: /* absolute */
2472 while (length--) {
2473 c = *bits++;
2474 if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2475 if (!length--) break;
2476 if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2478 if ((bits - begin) & 1)
2479 bits++;
2487 /***********************************************************************
2488 * X11DRV_DIB_SetImageBits_8
2490 * SetDIBits for an 8-bit deep DIB.
2492 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
2493 DWORD srcwidth, DWORD dstwidth, int left,
2494 const int *colors, XImage *bmpImage,
2495 DWORD linebytes )
2497 DWORD x;
2498 int h;
2499 const BYTE* srcbyte;
2500 BYTE* dstbits;
2502 if (lines < 0 )
2504 lines = -lines;
2505 srcbits = srcbits + linebytes * (lines-1);
2506 linebytes = -linebytes;
2508 srcbits += left;
2509 srcbyte = srcbits;
2511 switch (bmpImage->depth) {
2512 case 15:
2513 case 16:
2514 #if defined(__i386__) && defined(__GNUC__)
2515 /* Some X servers might have 32 bit/ 16bit deep pixel */
2516 if (lines && dstwidth && (bmpImage->bits_per_pixel == 16) &&
2517 (ImageByteOrder(gdi_display)==LSBFirst) )
2519 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2520 /* FIXME: Does this really handle all these cases correctly? */
2521 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
2522 for (h = lines ; h--; ) {
2523 int _cl1,_cl2; /* temp outputs for asm below */
2524 /* Borrowed from DirectDraw */
2525 __asm__ __volatile__(
2526 "xor %%eax,%%eax\n"
2527 "cld\n"
2528 "1:\n"
2529 " lodsb\n"
2530 " movw (%%edx,%%eax,4),%%ax\n"
2531 " stosw\n"
2532 " xor %%eax,%%eax\n"
2533 " loop 1b\n"
2534 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2535 :"S" (srcbyte),
2536 "D" (dstbits),
2537 "c" (dstwidth),
2538 "d" (colors)
2539 :"eax", "cc", "memory"
2541 srcbyte = (srcbits += linebytes);
2542 dstbits -= bmpImage->bytes_per_line;
2544 return;
2546 break;
2547 #endif
2548 case 24:
2549 case 32:
2550 #if defined(__i386__) && defined(__GNUC__)
2551 if (lines && dstwidth && (bmpImage->bits_per_pixel == 32) &&
2552 (ImageByteOrder(gdi_display)==LSBFirst) )
2554 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2555 /* FIXME: Does this really handle both cases correctly? */
2556 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
2557 for (h = lines ; h--; ) {
2558 int _cl1,_cl2; /* temp outputs for asm below */
2559 /* Borrowed from DirectDraw */
2560 __asm__ __volatile__(
2561 "xor %%eax,%%eax\n"
2562 "cld\n"
2563 "1:\n"
2564 " lodsb\n"
2565 " movl (%%edx,%%eax,4),%%eax\n"
2566 " stosl\n"
2567 " xor %%eax,%%eax\n"
2568 " loop 1b\n"
2569 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2570 :"S" (srcbyte),
2571 "D" (dstbits),
2572 "c" (dstwidth),
2573 "d" (colors)
2574 :"eax", "cc", "memory"
2576 srcbyte = (srcbits += linebytes);
2577 dstbits -= bmpImage->bytes_per_line;
2579 return;
2581 break;
2582 #endif
2583 default:
2584 break; /* use slow generic case below */
2587 /* ==== pal 8 dib -> any bmp format ==== */
2588 for (h=lines-1; h>=0; h--) {
2589 for (x=left; x<dstwidth+left; x++) {
2590 XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
2592 srcbyte = (srcbits += linebytes);
2596 /***********************************************************************
2597 * X11DRV_DIB_GetImageBits_8
2599 * GetDIBits for an 8-bit deep DIB.
2601 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
2602 DWORD srcwidth, DWORD dstwidth,
2603 RGBQUAD *colors, PALETTEENTRY *srccolors,
2604 XImage *bmpImage, DWORD linebytes )
2606 DWORD x;
2607 int h;
2608 BYTE* dstbyte;
2610 if (lines < 0 )
2612 lines = -lines;
2613 dstbits = dstbits + ( linebytes * (lines-1) );
2614 linebytes = -linebytes;
2618 * Hack for now
2619 * This condition is true when GetImageBits has been called by
2620 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
2621 * 256 colormaps, so we'll just use for for GetDIBits calls.
2622 * (In somes cases, in a updateDIBSection, the returned colors are bad too)
2624 if (!srccolors) goto updatesection;
2626 switch (bmpImage->depth) {
2627 case 1:
2628 case 4:
2629 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2631 /* ==== pal 1 bmp -> pal 8 dib ==== */
2632 /* ==== pal 4 bmp -> pal 8 dib ==== */
2633 for (h=lines-1; h>=0; h--) {
2634 dstbyte=dstbits;
2635 for (x=0; x<dstwidth; x++) {
2636 PALETTEENTRY srcval;
2637 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2638 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2639 srcval.peRed,
2640 srcval.peGreen,
2641 srcval.peBlue);
2643 dstbits += linebytes;
2645 } else {
2646 goto notsupported;
2648 break;
2650 case 8:
2651 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2652 /* ==== pal 8 bmp -> pal 8 dib ==== */
2653 const void* srcbits;
2654 const BYTE* srcpixel;
2656 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2657 for (h=0; h<lines; h++) {
2658 srcpixel=srcbits;
2659 dstbyte=dstbits;
2660 for (x = 0; x < dstwidth; x++) {
2661 PALETTEENTRY srcval;
2662 srcval=srccolors[(int)*srcpixel++];
2663 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2664 srcval.peRed,
2665 srcval.peGreen,
2666 srcval.peBlue);
2668 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2669 dstbits += linebytes;
2671 } else {
2672 goto notsupported;
2674 break;
2676 case 15:
2677 case 16:
2679 const void* srcbits;
2680 const WORD* srcpixel;
2681 BYTE* dstbyte;
2683 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2685 if (bmpImage->green_mask==0x03e0) {
2686 if (bmpImage->red_mask==0x7c00) {
2687 /* ==== rgb 555 bmp -> pal 8 dib ==== */
2688 for (h=0; h<lines; h++) {
2689 srcpixel=srcbits;
2690 dstbyte=dstbits;
2691 for (x=0; x<dstwidth; x++) {
2692 WORD srcval;
2693 srcval=*srcpixel++;
2694 *dstbyte++=X11DRV_DIB_GetNearestIndex
2695 (colors, 256,
2696 ((srcval >> 7) & 0xf8) | /* r */
2697 ((srcval >> 12) & 0x07),
2698 ((srcval >> 2) & 0xf8) | /* g */
2699 ((srcval >> 7) & 0x07),
2700 ((srcval << 3) & 0xf8) | /* b */
2701 ((srcval >> 2) & 0x07) );
2703 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2704 dstbits += linebytes;
2706 } else if (bmpImage->blue_mask==0x7c00) {
2707 /* ==== bgr 555 bmp -> pal 8 dib ==== */
2708 for (h=0; h<lines; h++) {
2709 srcpixel=srcbits;
2710 dstbyte=dstbits;
2711 for (x=0; x<dstwidth; x++) {
2712 WORD srcval;
2713 srcval=*srcpixel++;
2714 *dstbyte++=X11DRV_DIB_GetNearestIndex
2715 (colors, 256,
2716 ((srcval << 3) & 0xf8) | /* r */
2717 ((srcval >> 2) & 0x07),
2718 ((srcval >> 2) & 0xf8) | /* g */
2719 ((srcval >> 7) & 0x07),
2720 ((srcval >> 7) & 0xf8) | /* b */
2721 ((srcval >> 12) & 0x07) );
2723 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2724 dstbits += linebytes;
2726 } else {
2727 goto notsupported;
2729 } else if (bmpImage->green_mask==0x07e0) {
2730 if (bmpImage->red_mask==0xf800) {
2731 /* ==== rgb 565 bmp -> pal 8 dib ==== */
2732 for (h=0; h<lines; h++) {
2733 srcpixel=srcbits;
2734 dstbyte=dstbits;
2735 for (x=0; x<dstwidth; x++) {
2736 WORD srcval;
2737 srcval=*srcpixel++;
2738 *dstbyte++=X11DRV_DIB_GetNearestIndex
2739 (colors, 256,
2740 ((srcval >> 8) & 0xf8) | /* r */
2741 ((srcval >> 13) & 0x07),
2742 ((srcval >> 3) & 0xfc) | /* g */
2743 ((srcval >> 9) & 0x03),
2744 ((srcval << 3) & 0xf8) | /* b */
2745 ((srcval >> 2) & 0x07) );
2747 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2748 dstbits += linebytes;
2750 } else if (bmpImage->blue_mask==0xf800) {
2751 /* ==== bgr 565 bmp -> pal 8 dib ==== */
2752 for (h=0; h<lines; h++) {
2753 srcpixel=srcbits;
2754 dstbyte=dstbits;
2755 for (x=0; x<dstwidth; x++) {
2756 WORD srcval;
2757 srcval=*srcpixel++;
2758 *dstbyte++=X11DRV_DIB_GetNearestIndex
2759 (colors, 256,
2760 ((srcval << 3) & 0xf8) | /* r */
2761 ((srcval >> 2) & 0x07),
2762 ((srcval >> 3) & 0xfc) | /* g */
2763 ((srcval >> 9) & 0x03),
2764 ((srcval >> 8) & 0xf8) | /* b */
2765 ((srcval >> 13) & 0x07) );
2767 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2768 dstbits += linebytes;
2770 } else {
2771 goto notsupported;
2773 } else {
2774 goto notsupported;
2777 break;
2779 case 24:
2780 case 32:
2782 const void* srcbits;
2783 const BYTE *srcbyte;
2784 BYTE* dstbyte;
2785 int bytes_per_pixel;
2787 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2788 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
2790 if (bmpImage->green_mask!=0x00ff00 ||
2791 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2792 goto notsupported;
2793 } else if (bmpImage->blue_mask==0xff) {
2794 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
2795 for (h=0; h<lines; h++) {
2796 srcbyte=srcbits;
2797 dstbyte=dstbits;
2798 for (x=0; x<dstwidth; x++) {
2799 *dstbyte++=X11DRV_DIB_GetNearestIndex
2800 (colors, 256,
2801 srcbyte[2],
2802 srcbyte[1],
2803 srcbyte[0]);
2804 srcbyte+=bytes_per_pixel;
2806 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2807 dstbits += linebytes;
2809 } else {
2810 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
2811 for (h=0; h<lines; h++) {
2812 srcbyte=srcbits;
2813 dstbyte=dstbits;
2814 for (x=0; x<dstwidth; x++) {
2815 *dstbyte++=X11DRV_DIB_GetNearestIndex
2816 (colors, 256,
2817 srcbyte[0],
2818 srcbyte[1],
2819 srcbyte[2]);
2820 srcbyte+=bytes_per_pixel;
2822 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2823 dstbits += linebytes;
2827 break;
2829 default:
2830 notsupported:
2831 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
2832 bmpImage->depth, bmpImage->red_mask,
2833 bmpImage->green_mask, bmpImage->blue_mask );
2834 updatesection:
2835 /* ==== any bmp format -> pal 8 dib ==== */
2836 for (h=lines-1; h>=0; h--) {
2837 dstbyte=dstbits;
2838 for (x=0; x<dstwidth; x++) {
2839 *dstbyte=X11DRV_DIB_MapColor
2840 ((int*)colors, 256,
2841 XGetPixel(bmpImage, x, h), *dstbyte);
2842 dstbyte++;
2844 dstbits += linebytes;
2846 break;
2850 /***********************************************************************
2851 * X11DRV_DIB_SetImageBits_RLE8
2853 * SetDIBits for an 8-bit deep compressed DIB.
2855 * This function rewritten 941113 by James Youngman. WINE blew out when I
2856 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
2858 * This was because the algorithm assumed that all RLE8 bitmaps end with the
2859 * 'End of bitmap' escape code. This code is very much laxer in what it
2860 * allows to end the expansion. Possibly too lax. See the note by
2861 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
2862 * bitmap should end with RleEnd, but on the other hand, software exists
2863 * that produces ones that don't and Windows 3.1 doesn't complain a bit
2864 * about it.
2866 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
2867 * James A. Youngman <mbcstjy@afs.man.ac.uk>
2868 * [JAY]
2870 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
2871 DWORD width, DWORD dstwidth,
2872 int left, int *colors,
2873 XImage *bmpImage )
2875 int x; /* X-positon on each line. Increases. */
2876 int y; /* Line #. Starts at lines-1, decreases */
2877 const BYTE *pIn = bits; /* Pointer to current position in bits */
2878 BYTE length; /* The length pf a run */
2879 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
2882 * Note that the bitmap data is stored by Windows starting at the
2883 * bottom line of the bitmap and going upwards. Within each line,
2884 * the data is stored left-to-right. That's the reason why line
2885 * goes from lines-1 to 0. [JAY]
2888 x = 0;
2889 y = lines - 1;
2890 while (y >= 0)
2892 length = *pIn++;
2895 * If the length byte is not zero (which is the escape value),
2896 * We have a run of length pixels all the same colour. The colour
2897 * index is stored next.
2899 * If the length byte is zero, we need to read the next byte to
2900 * know what to do. [JAY]
2902 if (length != 0)
2905 * [Run-Length] Encoded mode
2907 int color = colors[*pIn++];
2908 while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
2910 else
2913 * Escape codes (may be an absolute sequence though)
2915 escape_code = (*pIn++);
2916 switch(escape_code)
2918 case RLE_EOL:
2919 x = 0;
2920 y--;
2921 break;
2923 case RLE_END:
2924 /* Not all RLE8 bitmaps end with this code. For
2925 * example, Paint Shop Pro produces some that don't.
2926 * That's (I think) what caused the previous
2927 * implementation to fail. [JAY]
2929 return;
2931 case RLE_DELTA:
2932 x += (*pIn++);
2933 y -= (*pIn++);
2934 break;
2936 default: /* switch to absolute mode */
2937 length = escape_code;
2938 while (length--)
2940 int color = colors[*pIn++];
2941 if (x >= dstwidth)
2943 pIn += length;
2944 break;
2946 XPutPixel(bmpImage, x++, y, color);
2949 * If you think for a moment you'll realise that the
2950 * only time we could ever possibly read an odd
2951 * number of bytes is when there is a 0x00 (escape),
2952 * a value >0x02 (absolute mode) and then an odd-
2953 * length run. Therefore this is the only place we
2954 * need to worry about it. Everywhere else the
2955 * bytes are always read in pairs. [JAY]
2957 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
2958 break;
2959 } /* switch (escape_code) : Escape sequence */
2965 /***********************************************************************
2966 * X11DRV_DIB_SetImageBits_16
2968 * SetDIBits for a 16-bit deep DIB.
2970 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
2971 DWORD srcwidth, DWORD dstwidth, int left,
2972 X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
2973 XImage *bmpImage, DWORD linebytes )
2975 DWORD x;
2976 int h;
2978 if (lines < 0 )
2980 lines = -lines;
2981 srcbits = srcbits + ( linebytes * (lines-1));
2982 linebytes = -linebytes;
2985 switch (bmpImage->depth)
2987 case 15:
2988 case 16:
2990 char* dstbits;
2992 srcbits=srcbits+left*2;
2993 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2995 if (bmpImage->green_mask==0x03e0) {
2996 if (gSrc==bmpImage->green_mask) {
2997 if (rSrc==bmpImage->red_mask) {
2998 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
2999 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
3000 X11DRV_DIB_Convert_any_asis
3001 (dstwidth,lines,2,
3002 srcbits,linebytes,
3003 dstbits,-bmpImage->bytes_per_line);
3004 } else if (rSrc==bmpImage->blue_mask) {
3005 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
3006 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
3007 X11DRV_DIB_Convert_555_reverse
3008 (dstwidth,lines,
3009 srcbits,linebytes,
3010 dstbits,-bmpImage->bytes_per_line);
3012 } else {
3013 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
3014 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
3015 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
3016 X11DRV_DIB_Convert_565_to_555_asis
3017 (dstwidth,lines,
3018 srcbits,linebytes,
3019 dstbits,-bmpImage->bytes_per_line);
3020 } else {
3021 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
3022 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
3023 X11DRV_DIB_Convert_565_to_555_reverse
3024 (dstwidth,lines,
3025 srcbits,linebytes,
3026 dstbits,-bmpImage->bytes_per_line);
3029 } else if (bmpImage->green_mask==0x07e0) {
3030 if (gSrc==bmpImage->green_mask) {
3031 if (rSrc==bmpImage->red_mask) {
3032 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
3033 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
3034 X11DRV_DIB_Convert_any_asis
3035 (dstwidth,lines,2,
3036 srcbits,linebytes,
3037 dstbits,-bmpImage->bytes_per_line);
3038 } else {
3039 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
3040 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
3041 X11DRV_DIB_Convert_565_reverse
3042 (dstwidth,lines,
3043 srcbits,linebytes,
3044 dstbits,-bmpImage->bytes_per_line);
3046 } else {
3047 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
3048 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
3049 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
3050 X11DRV_DIB_Convert_555_to_565_asis
3051 (dstwidth,lines,
3052 srcbits,linebytes,
3053 dstbits,-bmpImage->bytes_per_line);
3054 } else {
3055 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
3056 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
3057 X11DRV_DIB_Convert_555_to_565_reverse
3058 (dstwidth,lines,
3059 srcbits,linebytes,
3060 dstbits,-bmpImage->bytes_per_line);
3063 } else {
3064 goto notsupported;
3067 break;
3069 case 24:
3070 if (bmpImage->bits_per_pixel==24) {
3071 char* dstbits;
3073 srcbits=srcbits+left*2;
3074 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3076 if (bmpImage->green_mask!=0x00ff00 ||
3077 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3078 goto notsupported;
3079 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3080 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3081 if (gSrc==0x03e0) {
3082 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
3083 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
3084 X11DRV_DIB_Convert_555_to_888_asis
3085 (dstwidth,lines,
3086 srcbits,linebytes,
3087 dstbits,-bmpImage->bytes_per_line);
3088 } else {
3089 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
3090 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
3091 X11DRV_DIB_Convert_565_to_888_asis
3092 (dstwidth,lines,
3093 srcbits,linebytes,
3094 dstbits,-bmpImage->bytes_per_line);
3096 } else {
3097 if (gSrc==0x03e0) {
3098 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
3099 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
3100 X11DRV_DIB_Convert_555_to_888_reverse
3101 (dstwidth,lines,
3102 srcbits,linebytes,
3103 dstbits,-bmpImage->bytes_per_line);
3104 } else {
3105 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
3106 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
3107 X11DRV_DIB_Convert_565_to_888_reverse
3108 (dstwidth,lines,
3109 srcbits,linebytes,
3110 dstbits,-bmpImage->bytes_per_line);
3113 break;
3115 /* Fall through */
3117 case 32:
3119 char* dstbits;
3121 srcbits=srcbits+left*2;
3122 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3124 if (bmpImage->green_mask!=0x00ff00 ||
3125 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3126 goto notsupported;
3127 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3128 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3129 if (gSrc==0x03e0) {
3130 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
3131 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
3132 X11DRV_DIB_Convert_555_to_0888_asis
3133 (dstwidth,lines,
3134 srcbits,linebytes,
3135 dstbits,-bmpImage->bytes_per_line);
3136 } else {
3137 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
3138 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
3139 X11DRV_DIB_Convert_565_to_0888_asis
3140 (dstwidth,lines,
3141 srcbits,linebytes,
3142 dstbits,-bmpImage->bytes_per_line);
3144 } else {
3145 if (gSrc==0x03e0) {
3146 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
3147 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
3148 X11DRV_DIB_Convert_555_to_0888_reverse
3149 (dstwidth,lines,
3150 srcbits,linebytes,
3151 dstbits,-bmpImage->bytes_per_line);
3152 } else {
3153 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
3154 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
3155 X11DRV_DIB_Convert_565_to_0888_reverse
3156 (dstwidth,lines,
3157 srcbits,linebytes,
3158 dstbits,-bmpImage->bytes_per_line);
3162 break;
3164 default:
3165 notsupported:
3166 WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3167 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3168 bmpImage->green_mask, bmpImage->blue_mask );
3169 /* fall through */
3170 case 1:
3171 case 4:
3172 case 8:
3174 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
3175 const WORD* srcpixel;
3176 int rShift1,gShift1,bShift1;
3177 int rShift2,gShift2,bShift2;
3178 BYTE gMask1,gMask2;
3180 /* Set color scaling values */
3181 rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
3182 gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
3183 bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
3184 rShift2=rShift1+5;
3185 gShift2=gShift1+5;
3186 bShift2=bShift1+5;
3187 if (gSrc==0x03e0) {
3188 /* Green has 5 bits, like the others */
3189 gMask1=0xf8;
3190 gMask2=0x07;
3191 } else {
3192 /* Green has 6 bits, not 5. Compensate. */
3193 gShift1++;
3194 gShift2+=2;
3195 gMask1=0xfc;
3196 gMask2=0x03;
3199 srcbits+=2*left;
3201 /* We could split it into four separate cases to optimize
3202 * but it is probably not worth it.
3204 for (h=lines-1; h>=0; h--) {
3205 srcpixel=(const WORD*)srcbits;
3206 for (x=left; x<dstwidth+left; x++) {
3207 DWORD srcval;
3208 BYTE red,green,blue;
3209 srcval=*srcpixel++ << 16;
3210 red= ((srcval >> rShift1) & 0xf8) |
3211 ((srcval >> rShift2) & 0x07);
3212 green=((srcval >> gShift1) & gMask1) |
3213 ((srcval >> gShift2) & gMask2);
3214 blue= ((srcval >> bShift1) & 0xf8) |
3215 ((srcval >> bShift2) & 0x07);
3216 XPutPixel(bmpImage, x, h,
3217 X11DRV_PALETTE_ToPhysical
3218 (physDev, RGB(red,green,blue)));
3220 srcbits += linebytes;
3223 break;
3228 /***********************************************************************
3229 * X11DRV_DIB_GetImageBits_16
3231 * GetDIBits for an 16-bit deep DIB.
3233 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
3234 DWORD dstwidth, DWORD srcwidth,
3235 PALETTEENTRY *srccolors,
3236 DWORD rDst, DWORD gDst, DWORD bDst,
3237 XImage *bmpImage, DWORD dibpitch )
3239 DWORD x;
3240 int h;
3242 DWORD linebytes = dibpitch;
3244 if (lines < 0 )
3246 lines = -lines;
3247 dstbits = dstbits + ( linebytes * (lines-1));
3248 linebytes = -linebytes;
3251 switch (bmpImage->depth)
3253 case 15:
3254 case 16:
3256 const char* srcbits;
3258 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3260 if (bmpImage->green_mask==0x03e0) {
3261 if (gDst==bmpImage->green_mask) {
3262 if (rDst==bmpImage->red_mask) {
3263 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
3264 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
3265 X11DRV_DIB_Convert_any_asis
3266 (dstwidth,lines,2,
3267 srcbits,-bmpImage->bytes_per_line,
3268 dstbits,linebytes);
3269 } else {
3270 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
3271 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
3272 X11DRV_DIB_Convert_555_reverse
3273 (dstwidth,lines,
3274 srcbits,-bmpImage->bytes_per_line,
3275 dstbits,linebytes);
3277 } else {
3278 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3279 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
3280 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
3281 X11DRV_DIB_Convert_555_to_565_asis
3282 (dstwidth,lines,
3283 srcbits,-bmpImage->bytes_per_line,
3284 dstbits,linebytes);
3285 } else {
3286 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
3287 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
3288 X11DRV_DIB_Convert_555_to_565_reverse
3289 (dstwidth,lines,
3290 srcbits,-bmpImage->bytes_per_line,
3291 dstbits,linebytes);
3294 } else if (bmpImage->green_mask==0x07e0) {
3295 if (gDst==bmpImage->green_mask) {
3296 if (rDst == bmpImage->red_mask) {
3297 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
3298 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
3299 X11DRV_DIB_Convert_any_asis
3300 (dstwidth,lines,2,
3301 srcbits,-bmpImage->bytes_per_line,
3302 dstbits,linebytes);
3303 } else {
3304 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
3305 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
3306 X11DRV_DIB_Convert_565_reverse
3307 (dstwidth,lines,
3308 srcbits,-bmpImage->bytes_per_line,
3309 dstbits,linebytes);
3311 } else {
3312 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3313 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
3314 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
3315 X11DRV_DIB_Convert_565_to_555_asis
3316 (dstwidth,lines,
3317 srcbits,-bmpImage->bytes_per_line,
3318 dstbits,linebytes);
3319 } else {
3320 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
3321 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
3322 X11DRV_DIB_Convert_565_to_555_reverse
3323 (dstwidth,lines,
3324 srcbits,-bmpImage->bytes_per_line,
3325 dstbits,linebytes);
3328 } else {
3329 goto notsupported;
3332 break;
3334 case 24:
3335 if (bmpImage->bits_per_pixel == 24) {
3336 const char* srcbits;
3338 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3340 if (bmpImage->green_mask!=0x00ff00 ||
3341 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3342 goto notsupported;
3343 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3344 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3345 if (gDst==0x03e0) {
3346 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
3347 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
3348 X11DRV_DIB_Convert_888_to_555_asis
3349 (dstwidth,lines,
3350 srcbits,-bmpImage->bytes_per_line,
3351 dstbits,linebytes);
3352 } else {
3353 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3354 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3355 X11DRV_DIB_Convert_888_to_565_asis
3356 (dstwidth,lines,
3357 srcbits,-bmpImage->bytes_per_line,
3358 dstbits,linebytes);
3360 } else {
3361 if (gDst==0x03e0) {
3362 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
3363 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
3364 X11DRV_DIB_Convert_888_to_555_reverse
3365 (dstwidth,lines,
3366 srcbits,-bmpImage->bytes_per_line,
3367 dstbits,linebytes);
3368 } else {
3369 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
3370 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
3371 X11DRV_DIB_Convert_888_to_565_reverse
3372 (dstwidth,lines,
3373 srcbits,-bmpImage->bytes_per_line,
3374 dstbits,linebytes);
3377 break;
3379 /* Fall through */
3381 case 32:
3383 const char* srcbits;
3385 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3387 if (bmpImage->green_mask!=0x00ff00 ||
3388 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3389 goto notsupported;
3390 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3391 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3392 if (gDst==0x03e0) {
3393 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
3394 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
3395 X11DRV_DIB_Convert_0888_to_555_asis
3396 (dstwidth,lines,
3397 srcbits,-bmpImage->bytes_per_line,
3398 dstbits,linebytes);
3399 } else {
3400 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
3401 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
3402 X11DRV_DIB_Convert_0888_to_565_asis
3403 (dstwidth,lines,
3404 srcbits,-bmpImage->bytes_per_line,
3405 dstbits,linebytes);
3407 } else {
3408 if (gDst==0x03e0) {
3409 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
3410 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
3411 X11DRV_DIB_Convert_0888_to_555_reverse
3412 (dstwidth,lines,
3413 srcbits,-bmpImage->bytes_per_line,
3414 dstbits,linebytes);
3415 } else {
3416 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
3417 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
3418 X11DRV_DIB_Convert_0888_to_565_reverse
3419 (dstwidth,lines,
3420 srcbits,-bmpImage->bytes_per_line,
3421 dstbits,linebytes);
3425 break;
3427 case 1:
3428 case 4:
3429 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3430 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
3431 int rShift,gShift,bShift;
3432 WORD* dstpixel;
3434 /* Shift everything 16 bits left so that all shifts are >0,
3435 * even for BGR DIBs. Then a single >> 16 will bring everything
3436 * back into place.
3438 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3439 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3440 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3441 if (gDst==0x07e0) {
3442 /* 6 bits for the green */
3443 gShift++;
3445 rDst=rDst << 16;
3446 gDst=gDst << 16;
3447 bDst=bDst << 16;
3448 for (h = lines - 1; h >= 0; h--) {
3449 dstpixel=(LPWORD)dstbits;
3450 for (x = 0; x < dstwidth; x++) {
3451 PALETTEENTRY srcval;
3452 DWORD dstval;
3453 srcval=srccolors[XGetPixel(bmpImage, x, h)];
3454 dstval=((srcval.peRed << rShift) & rDst) |
3455 ((srcval.peGreen << gShift) & gDst) |
3456 ((srcval.peBlue << bShift) & bDst);
3457 *dstpixel++=dstval >> 16;
3459 dstbits += linebytes;
3461 } else {
3462 goto notsupported;
3464 break;
3466 case 8:
3467 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3468 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
3469 int rShift,gShift,bShift;
3470 const BYTE* srcbits;
3471 const BYTE* srcpixel;
3472 WORD* dstpixel;
3474 /* Shift everything 16 bits left so that all shifts are >0,
3475 * even for BGR DIBs. Then a single >> 16 will bring everything
3476 * back into place.
3478 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3479 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3480 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3481 if (gDst==0x07e0) {
3482 /* 6 bits for the green */
3483 gShift++;
3485 rDst=rDst << 16;
3486 gDst=gDst << 16;
3487 bDst=bDst << 16;
3488 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3489 for (h=0; h<lines; h++) {
3490 srcpixel=srcbits;
3491 dstpixel=(LPWORD)dstbits;
3492 for (x = 0; x < dstwidth; x++) {
3493 PALETTEENTRY srcval;
3494 DWORD dstval;
3495 srcval=srccolors[(int)*srcpixel++];
3496 dstval=((srcval.peRed << rShift) & rDst) |
3497 ((srcval.peGreen << gShift) & gDst) |
3498 ((srcval.peBlue << bShift) & bDst);
3499 *dstpixel++=dstval >> 16;
3501 srcbits -= bmpImage->bytes_per_line;
3502 dstbits += linebytes;
3504 } else {
3505 goto notsupported;
3507 break;
3509 default:
3510 notsupported:
3512 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
3513 int rShift,gShift,bShift;
3514 WORD* dstpixel;
3516 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
3517 bmpImage->depth, bmpImage->red_mask,
3518 bmpImage->green_mask, bmpImage->blue_mask,
3519 rDst, gDst, bDst);
3521 /* Shift everything 16 bits left so that all shifts are >0,
3522 * even for BGR DIBs. Then a single >> 16 will bring everything
3523 * back into place.
3525 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3526 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3527 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3528 if (gDst==0x07e0) {
3529 /* 6 bits for the green */
3530 gShift++;
3532 rDst=rDst << 16;
3533 gDst=gDst << 16;
3534 bDst=bDst << 16;
3535 for (h = lines - 1; h >= 0; h--) {
3536 dstpixel=(LPWORD)dstbits;
3537 for (x = 0; x < dstwidth; x++) {
3538 COLORREF srcval;
3539 DWORD dstval;
3540 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3541 dstval=((GetRValue(srcval) << rShift) & rDst) |
3542 ((GetGValue(srcval) << gShift) & gDst) |
3543 ((GetBValue(srcval) << bShift) & bDst);
3544 *dstpixel++=dstval >> 16;
3546 dstbits += linebytes;
3549 break;
3554 /***********************************************************************
3555 * X11DRV_DIB_SetImageBits_24
3557 * SetDIBits for a 24-bit deep DIB.
3559 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
3560 DWORD srcwidth, DWORD dstwidth, int left,
3561 X11DRV_PDEVICE *physDev,
3562 DWORD rSrc, DWORD gSrc, DWORD bSrc,
3563 XImage *bmpImage, DWORD linebytes )
3565 DWORD x;
3566 int h;
3568 if (lines < 0 )
3570 lines = -lines;
3571 srcbits = srcbits + linebytes * (lines - 1);
3572 linebytes = -linebytes;
3575 switch (bmpImage->depth)
3577 case 24:
3578 if (bmpImage->bits_per_pixel==24) {
3579 char* dstbits;
3581 srcbits=srcbits+left*3;
3582 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3584 if (bmpImage->green_mask!=0x00ff00 ||
3585 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3586 goto notsupported;
3587 } else if (rSrc==bmpImage->red_mask) {
3588 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
3589 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
3590 X11DRV_DIB_Convert_any_asis
3591 (dstwidth,lines,3,
3592 srcbits,linebytes,
3593 dstbits,-bmpImage->bytes_per_line);
3594 } else {
3595 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
3596 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
3597 X11DRV_DIB_Convert_888_reverse
3598 (dstwidth,lines,
3599 srcbits,linebytes,
3600 dstbits,-bmpImage->bytes_per_line);
3602 break;
3604 /* fall through */
3606 case 32:
3608 char* dstbits;
3610 srcbits=srcbits+left*3;
3611 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3613 if (bmpImage->green_mask!=0x00ff00 ||
3614 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3615 goto notsupported;
3616 } else if (rSrc==bmpImage->red_mask) {
3617 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
3618 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
3619 X11DRV_DIB_Convert_888_to_0888_asis
3620 (dstwidth,lines,
3621 srcbits,linebytes,
3622 dstbits,-bmpImage->bytes_per_line);
3623 } else {
3624 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
3625 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
3626 X11DRV_DIB_Convert_888_to_0888_reverse
3627 (dstwidth,lines,
3628 srcbits,linebytes,
3629 dstbits,-bmpImage->bytes_per_line);
3631 break;
3634 case 15:
3635 case 16:
3637 char* dstbits;
3639 srcbits=srcbits+left*3;
3640 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
3642 if (bmpImage->green_mask==0x03e0) {
3643 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
3644 (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3645 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
3646 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
3647 X11DRV_DIB_Convert_888_to_555_asis
3648 (dstwidth,lines,
3649 srcbits,linebytes,
3650 dstbits,-bmpImage->bytes_per_line);
3651 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
3652 (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
3653 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
3654 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
3655 X11DRV_DIB_Convert_888_to_555_reverse
3656 (dstwidth,lines,
3657 srcbits,linebytes,
3658 dstbits,-bmpImage->bytes_per_line);
3659 } else {
3660 goto notsupported;
3662 } else if (bmpImage->green_mask==0x07e0) {
3663 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
3664 (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
3665 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
3666 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
3667 X11DRV_DIB_Convert_888_to_565_asis
3668 (dstwidth,lines,
3669 srcbits,linebytes,
3670 dstbits,-bmpImage->bytes_per_line);
3671 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
3672 (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
3673 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
3674 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
3675 X11DRV_DIB_Convert_888_to_565_reverse
3676 (dstwidth,lines,
3677 srcbits,linebytes,
3678 dstbits,-bmpImage->bytes_per_line);
3679 } else {
3680 goto notsupported;
3682 } else {
3683 goto notsupported;
3686 break;
3688 default:
3689 notsupported:
3690 WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3691 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3692 bmpImage->green_mask, bmpImage->blue_mask );
3693 /* fall through */
3694 case 1:
3695 case 4:
3696 case 8:
3698 /* ==== rgb 888 dib -> any bmp bormat ==== */
3699 const BYTE* srcbyte;
3701 /* Windows only supports one 24bpp DIB format: RGB888 */
3702 srcbits+=left*3;
3703 for (h = lines - 1; h >= 0; h--) {
3704 srcbyte=(const BYTE*)srcbits;
3705 for (x = left; x < dstwidth+left; x++) {
3706 XPutPixel(bmpImage, x, h,
3707 X11DRV_PALETTE_ToPhysical
3708 (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
3709 srcbyte+=3;
3711 srcbits += linebytes;
3714 break;
3719 /***********************************************************************
3720 * X11DRV_DIB_GetImageBits_24
3722 * GetDIBits for an 24-bit deep DIB.
3724 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
3725 DWORD dstwidth, DWORD srcwidth,
3726 PALETTEENTRY *srccolors,
3727 DWORD rDst, DWORD gDst, DWORD bDst,
3728 XImage *bmpImage, DWORD linebytes )
3730 DWORD x;
3731 int h;
3733 if (lines < 0 )
3735 lines = -lines;
3736 dstbits = dstbits + ( linebytes * (lines-1) );
3737 linebytes = -linebytes;
3740 switch (bmpImage->depth)
3742 case 24:
3743 if (bmpImage->bits_per_pixel==24) {
3744 const char* srcbits;
3746 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3748 if (bmpImage->green_mask!=0x00ff00 ||
3749 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3750 goto notsupported;
3751 } else if (rDst==bmpImage->red_mask) {
3752 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
3753 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
3754 X11DRV_DIB_Convert_any_asis
3755 (dstwidth,lines,3,
3756 srcbits,-bmpImage->bytes_per_line,
3757 dstbits,linebytes);
3758 } else {
3759 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
3760 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
3761 X11DRV_DIB_Convert_888_reverse
3762 (dstwidth,lines,
3763 srcbits,-bmpImage->bytes_per_line,
3764 dstbits,linebytes);
3766 break;
3768 /* fall through */
3770 case 32:
3772 const char* srcbits;
3774 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3776 if (bmpImage->green_mask!=0x00ff00 ||
3777 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3778 goto notsupported;
3779 } else if (rDst==bmpImage->red_mask) {
3780 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3781 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3782 X11DRV_DIB_Convert_0888_to_888_asis
3783 (dstwidth,lines,
3784 srcbits,-bmpImage->bytes_per_line,
3785 dstbits,linebytes);
3786 } else {
3787 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3788 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3789 X11DRV_DIB_Convert_0888_to_888_reverse
3790 (dstwidth,lines,
3791 srcbits,-bmpImage->bytes_per_line,
3792 dstbits,linebytes);
3794 break;
3797 case 15:
3798 case 16:
3800 const char* srcbits;
3802 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3804 if (bmpImage->green_mask==0x03e0) {
3805 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
3806 (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3807 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
3808 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
3809 X11DRV_DIB_Convert_555_to_888_asis
3810 (dstwidth,lines,
3811 srcbits,-bmpImage->bytes_per_line,
3812 dstbits,linebytes);
3813 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
3814 (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
3815 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
3816 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
3817 X11DRV_DIB_Convert_555_to_888_reverse
3818 (dstwidth,lines,
3819 srcbits,-bmpImage->bytes_per_line,
3820 dstbits,linebytes);
3821 } else {
3822 goto notsupported;
3824 } else if (bmpImage->green_mask==0x07e0) {
3825 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
3826 (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
3827 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
3828 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
3829 X11DRV_DIB_Convert_565_to_888_asis
3830 (dstwidth,lines,
3831 srcbits,-bmpImage->bytes_per_line,
3832 dstbits,linebytes);
3833 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
3834 (bDst==0xff && bmpImage->blue_mask==0xf800)) {
3835 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
3836 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
3837 X11DRV_DIB_Convert_565_to_888_reverse
3838 (dstwidth,lines,
3839 srcbits,-bmpImage->bytes_per_line,
3840 dstbits,linebytes);
3841 } else {
3842 goto notsupported;
3844 } else {
3845 goto notsupported;
3848 break;
3850 case 1:
3851 case 4:
3852 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3853 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
3854 BYTE* dstbyte;
3856 /* Windows only supports one 24bpp DIB format: rgb 888 */
3857 for (h = lines - 1; h >= 0; h--) {
3858 dstbyte=dstbits;
3859 for (x = 0; x < dstwidth; x++) {
3860 PALETTEENTRY srcval;
3861 srcval=srccolors[XGetPixel(bmpImage, x, h)];
3862 dstbyte[0]=srcval.peBlue;
3863 dstbyte[1]=srcval.peGreen;
3864 dstbyte[2]=srcval.peRed;
3865 dstbyte+=3;
3867 dstbits += linebytes;
3869 } else {
3870 goto notsupported;
3872 break;
3874 case 8:
3875 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors) {
3876 /* ==== pal 8 bmp -> rgb 888 dib ==== */
3877 const void* srcbits;
3878 const BYTE* srcpixel;
3879 BYTE* dstbyte;
3881 /* Windows only supports one 24bpp DIB format: rgb 888 */
3882 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3883 for (h = lines - 1; h >= 0; h--) {
3884 srcpixel=srcbits;
3885 dstbyte=dstbits;
3886 for (x = 0; x < dstwidth; x++ ) {
3887 PALETTEENTRY srcval;
3888 srcval=srccolors[(int)*srcpixel++];
3889 dstbyte[0]=srcval.peBlue;
3890 dstbyte[1]=srcval.peGreen;
3891 dstbyte[2]=srcval.peRed;
3892 dstbyte+=3;
3894 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
3895 dstbits += linebytes;
3897 } else {
3898 goto notsupported;
3900 break;
3902 default:
3903 notsupported:
3905 /* ==== any bmp format -> 888 dib ==== */
3906 BYTE* dstbyte;
3908 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
3909 bmpImage->depth, bmpImage->red_mask,
3910 bmpImage->green_mask, bmpImage->blue_mask,
3911 rDst, gDst, bDst );
3913 /* Windows only supports one 24bpp DIB format: rgb 888 */
3914 for (h = lines - 1; h >= 0; h--) {
3915 dstbyte=dstbits;
3916 for (x = 0; x < dstwidth; x++) {
3917 COLORREF srcval=X11DRV_PALETTE_ToLogical
3918 (XGetPixel( bmpImage, x, h ));
3919 dstbyte[0]=GetBValue(srcval);
3920 dstbyte[1]=GetGValue(srcval);
3921 dstbyte[2]=GetRValue(srcval);
3922 dstbyte+=3;
3924 dstbits += linebytes;
3927 break;
3932 /***********************************************************************
3933 * X11DRV_DIB_SetImageBits_32
3935 * SetDIBits for a 32-bit deep DIB.
3937 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
3938 DWORD srcwidth, DWORD dstwidth, int left,
3939 X11DRV_PDEVICE *physDev,
3940 DWORD rSrc, DWORD gSrc, DWORD bSrc,
3941 XImage *bmpImage,
3942 DWORD linebytes)
3944 DWORD x, *ptr;
3945 int h;
3947 if (lines < 0 )
3949 lines = -lines;
3950 srcbits = srcbits + ( linebytes * (lines-1) );
3951 linebytes = -linebytes;
3954 ptr = (DWORD *) srcbits + left;
3956 switch (bmpImage->depth)
3958 case 24:
3959 if (bmpImage->bits_per_pixel==24) {
3960 char* dstbits;
3962 srcbits=srcbits+left*4;
3963 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3965 if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
3966 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
3967 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
3968 X11DRV_DIB_Convert_0888_to_888_asis
3969 (dstwidth,lines,
3970 srcbits,linebytes,
3971 dstbits,-bmpImage->bytes_per_line);
3972 } else if (bmpImage->green_mask!=0x00ff00 ||
3973 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3974 goto notsupported;
3975 /* the tests below assume sane bmpImage masks */
3976 } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
3977 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
3978 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
3979 X11DRV_DIB_Convert_0888_to_888_reverse
3980 (dstwidth,lines,
3981 srcbits,linebytes,
3982 dstbits,-bmpImage->bytes_per_line);
3983 } else if (bmpImage->blue_mask==0xff) {
3984 /* ==== any 0888 dib -> rgb 888 bmp ==== */
3985 X11DRV_DIB_Convert_any0888_to_rgb888
3986 (dstwidth,lines,
3987 srcbits,linebytes,
3988 rSrc,gSrc,bSrc,
3989 dstbits,-bmpImage->bytes_per_line);
3990 } else {
3991 /* ==== any 0888 dib -> bgr 888 bmp ==== */
3992 X11DRV_DIB_Convert_any0888_to_bgr888
3993 (dstwidth,lines,
3994 srcbits,linebytes,
3995 rSrc,gSrc,bSrc,
3996 dstbits,-bmpImage->bytes_per_line);
3998 break;
4000 /* fall through */
4002 case 32:
4004 char* dstbits;
4006 srcbits=srcbits+left*4;
4007 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
4009 if (gSrc==bmpImage->green_mask) {
4010 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
4011 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
4012 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
4013 X11DRV_DIB_Convert_any_asis
4014 (dstwidth,lines,4,
4015 srcbits,linebytes,
4016 dstbits,-bmpImage->bytes_per_line);
4017 } else if (bmpImage->green_mask!=0x00ff00 ||
4018 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4019 goto notsupported;
4020 /* the tests below assume sane bmpImage masks */
4021 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
4022 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
4023 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
4024 X11DRV_DIB_Convert_0888_reverse
4025 (dstwidth,lines,
4026 srcbits,linebytes,
4027 dstbits,-bmpImage->bytes_per_line);
4028 } else {
4029 /* ==== any 0888 dib -> any 0888 bmp ==== */
4030 X11DRV_DIB_Convert_0888_any
4031 (dstwidth,lines,
4032 srcbits,linebytes,
4033 rSrc,gSrc,bSrc,
4034 dstbits,-bmpImage->bytes_per_line,
4035 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4037 } else if (bmpImage->green_mask!=0x00ff00 ||
4038 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4039 goto notsupported;
4040 /* the tests below assume sane bmpImage masks */
4041 } else {
4042 /* ==== any 0888 dib -> any 0888 bmp ==== */
4043 X11DRV_DIB_Convert_0888_any
4044 (dstwidth,lines,
4045 srcbits,linebytes,
4046 rSrc,gSrc,bSrc,
4047 dstbits,-bmpImage->bytes_per_line,
4048 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4051 break;
4053 case 15:
4054 case 16:
4056 char* dstbits;
4058 srcbits=srcbits+left*4;
4059 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
4061 if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
4062 if (bmpImage->green_mask==0x03e0) {
4063 if (bmpImage->red_mask==0x7f00) {
4064 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
4065 X11DRV_DIB_Convert_0888_to_555_asis
4066 (dstwidth,lines,
4067 srcbits,linebytes,
4068 dstbits,-bmpImage->bytes_per_line);
4069 } else if (bmpImage->blue_mask==0x7f00) {
4070 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
4071 X11DRV_DIB_Convert_0888_to_555_reverse
4072 (dstwidth,lines,
4073 srcbits,linebytes,
4074 dstbits,-bmpImage->bytes_per_line);
4075 } else {
4076 goto notsupported;
4078 } else if (bmpImage->green_mask==0x07e0) {
4079 if (bmpImage->red_mask==0xf800) {
4080 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
4081 X11DRV_DIB_Convert_0888_to_565_asis
4082 (dstwidth,lines,
4083 srcbits,linebytes,
4084 dstbits,-bmpImage->bytes_per_line);
4085 } else if (bmpImage->blue_mask==0xf800) {
4086 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
4087 X11DRV_DIB_Convert_0888_to_565_reverse
4088 (dstwidth,lines,
4089 srcbits,linebytes,
4090 dstbits,-bmpImage->bytes_per_line);
4091 } else {
4092 goto notsupported;
4094 } else {
4095 goto notsupported;
4097 } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
4098 if (bmpImage->green_mask==0x03e0) {
4099 if (bmpImage->blue_mask==0x7f00) {
4100 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
4101 X11DRV_DIB_Convert_0888_to_555_asis
4102 (dstwidth,lines,
4103 srcbits,linebytes,
4104 dstbits,-bmpImage->bytes_per_line);
4105 } else if (bmpImage->red_mask==0x7f00) {
4106 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
4107 X11DRV_DIB_Convert_0888_to_555_reverse
4108 (dstwidth,lines,
4109 srcbits,linebytes,
4110 dstbits,-bmpImage->bytes_per_line);
4111 } else {
4112 goto notsupported;
4114 } else if (bmpImage->green_mask==0x07e0) {
4115 if (bmpImage->blue_mask==0xf800) {
4116 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
4117 X11DRV_DIB_Convert_0888_to_565_asis
4118 (dstwidth,lines,
4119 srcbits,linebytes,
4120 dstbits,-bmpImage->bytes_per_line);
4121 } else if (bmpImage->red_mask==0xf800) {
4122 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
4123 X11DRV_DIB_Convert_0888_to_565_reverse
4124 (dstwidth,lines,
4125 srcbits,linebytes,
4126 dstbits,-bmpImage->bytes_per_line);
4127 } else {
4128 goto notsupported;
4130 } else {
4131 goto notsupported;
4133 } else {
4134 if (bmpImage->green_mask==0x03e0 &&
4135 (bmpImage->red_mask==0x7f00 ||
4136 bmpImage->blue_mask==0x7f00)) {
4137 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
4138 X11DRV_DIB_Convert_any0888_to_5x5
4139 (dstwidth,lines,
4140 srcbits,linebytes,
4141 rSrc,gSrc,bSrc,
4142 dstbits,-bmpImage->bytes_per_line,
4143 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4144 } else if (bmpImage->green_mask==0x07e0 &&
4145 (bmpImage->red_mask==0xf800 ||
4146 bmpImage->blue_mask==0xf800)) {
4147 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
4148 X11DRV_DIB_Convert_any0888_to_5x5
4149 (dstwidth,lines,
4150 srcbits,linebytes,
4151 rSrc,gSrc,bSrc,
4152 dstbits,-bmpImage->bytes_per_line,
4153 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4154 } else {
4155 goto notsupported;
4159 break;
4161 default:
4162 notsupported:
4163 WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
4164 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
4165 bmpImage->green_mask, bmpImage->blue_mask );
4166 /* fall through */
4167 case 1:
4168 case 4:
4169 case 8:
4171 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
4172 const DWORD* srcpixel;
4173 int rShift,gShift,bShift;
4175 rShift=X11DRV_DIB_MaskToShift(rSrc);
4176 gShift=X11DRV_DIB_MaskToShift(gSrc);
4177 bShift=X11DRV_DIB_MaskToShift(bSrc);
4178 srcbits+=left*4;
4179 for (h = lines - 1; h >= 0; h--) {
4180 srcpixel=(const DWORD*)srcbits;
4181 for (x = left; x < dstwidth+left; x++) {
4182 DWORD srcvalue;
4183 BYTE red,green,blue;
4184 srcvalue=*srcpixel++;
4185 red= (srcvalue >> rShift) & 0xff;
4186 green=(srcvalue >> gShift) & 0xff;
4187 blue= (srcvalue >> bShift) & 0xff;
4188 XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
4189 (physDev, RGB(red,green,blue)));
4191 srcbits += linebytes;
4194 break;
4199 /***********************************************************************
4200 * X11DRV_DIB_GetImageBits_32
4202 * GetDIBits for an 32-bit deep DIB.
4204 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
4205 DWORD dstwidth, DWORD srcwidth,
4206 PALETTEENTRY *srccolors,
4207 DWORD rDst, DWORD gDst, DWORD bDst,
4208 XImage *bmpImage, DWORD linebytes )
4210 DWORD x;
4211 int h;
4212 BYTE *bits;
4214 if (lines < 0 )
4216 lines = -lines;
4217 dstbits = dstbits + ( linebytes * (lines-1) );
4218 linebytes = -linebytes;
4221 bits = dstbits;
4223 switch (bmpImage->depth)
4225 case 24:
4226 if (bmpImage->bits_per_pixel==24) {
4227 const void* srcbits;
4229 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4231 if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
4232 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
4233 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
4234 X11DRV_DIB_Convert_888_to_0888_asis
4235 (dstwidth,lines,
4236 srcbits,-bmpImage->bytes_per_line,
4237 dstbits,linebytes);
4238 } else if (bmpImage->green_mask!=0x00ff00 ||
4239 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4240 goto notsupported;
4241 /* the tests below assume sane bmpImage masks */
4242 } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
4243 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
4244 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
4245 X11DRV_DIB_Convert_888_to_0888_reverse
4246 (dstwidth,lines,
4247 srcbits,-bmpImage->bytes_per_line,
4248 dstbits,linebytes);
4249 } else if (bmpImage->blue_mask==0xff) {
4250 /* ==== rgb 888 bmp -> any 0888 dib ==== */
4251 X11DRV_DIB_Convert_rgb888_to_any0888
4252 (dstwidth,lines,
4253 srcbits,-bmpImage->bytes_per_line,
4254 dstbits,linebytes,
4255 rDst,gDst,bDst);
4256 } else {
4257 /* ==== bgr 888 bmp -> any 0888 dib ==== */
4258 X11DRV_DIB_Convert_bgr888_to_any0888
4259 (dstwidth,lines,
4260 srcbits,-bmpImage->bytes_per_line,
4261 dstbits,linebytes,
4262 rDst,gDst,bDst);
4264 break;
4266 /* fall through */
4268 case 32:
4270 const char* srcbits;
4272 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4274 if (gDst==bmpImage->green_mask) {
4275 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
4276 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
4277 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
4278 X11DRV_DIB_Convert_any_asis
4279 (dstwidth,lines,4,
4280 srcbits,-bmpImage->bytes_per_line,
4281 dstbits,linebytes);
4282 } else if (bmpImage->green_mask!=0x00ff00 ||
4283 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4284 goto notsupported;
4285 /* the tests below assume sane bmpImage masks */
4286 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
4287 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
4288 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
4289 X11DRV_DIB_Convert_0888_reverse
4290 (dstwidth,lines,
4291 srcbits,-bmpImage->bytes_per_line,
4292 dstbits,linebytes);
4293 } else {
4294 /* ==== any 0888 bmp -> any 0888 dib ==== */
4295 X11DRV_DIB_Convert_0888_any
4296 (dstwidth,lines,
4297 srcbits,-bmpImage->bytes_per_line,
4298 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4299 dstbits,linebytes,
4300 rDst,gDst,bDst);
4302 } else if (bmpImage->green_mask!=0x00ff00 ||
4303 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4304 goto notsupported;
4305 /* the tests below assume sane bmpImage masks */
4306 } else {
4307 /* ==== any 0888 bmp -> any 0888 dib ==== */
4308 X11DRV_DIB_Convert_0888_any
4309 (dstwidth,lines,
4310 srcbits,-bmpImage->bytes_per_line,
4311 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4312 dstbits,linebytes,
4313 rDst,gDst,bDst);
4316 break;
4318 case 15:
4319 case 16:
4321 const char* srcbits;
4323 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4325 if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
4326 if (bmpImage->green_mask==0x03e0) {
4327 if (bmpImage->red_mask==0x7f00) {
4328 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
4329 X11DRV_DIB_Convert_555_to_0888_asis
4330 (dstwidth,lines,
4331 srcbits,-bmpImage->bytes_per_line,
4332 dstbits,linebytes);
4333 } else if (bmpImage->blue_mask==0x7f00) {
4334 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
4335 X11DRV_DIB_Convert_555_to_0888_reverse
4336 (dstwidth,lines,
4337 srcbits,-bmpImage->bytes_per_line,
4338 dstbits,linebytes);
4339 } else {
4340 goto notsupported;
4342 } else if (bmpImage->green_mask==0x07e0) {
4343 if (bmpImage->red_mask==0xf800) {
4344 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
4345 X11DRV_DIB_Convert_565_to_0888_asis
4346 (dstwidth,lines,
4347 srcbits,-bmpImage->bytes_per_line,
4348 dstbits,linebytes);
4349 } else if (bmpImage->blue_mask==0xf800) {
4350 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
4351 X11DRV_DIB_Convert_565_to_0888_reverse
4352 (dstwidth,lines,
4353 srcbits,-bmpImage->bytes_per_line,
4354 dstbits,linebytes);
4355 } else {
4356 goto notsupported;
4358 } else {
4359 goto notsupported;
4361 } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
4362 if (bmpImage->green_mask==0x03e0) {
4363 if (bmpImage->blue_mask==0x7f00) {
4364 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
4365 X11DRV_DIB_Convert_555_to_0888_asis
4366 (dstwidth,lines,
4367 srcbits,-bmpImage->bytes_per_line,
4368 dstbits,linebytes);
4369 } else if (bmpImage->red_mask==0x7f00) {
4370 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
4371 X11DRV_DIB_Convert_555_to_0888_reverse
4372 (dstwidth,lines,
4373 srcbits,-bmpImage->bytes_per_line,
4374 dstbits,linebytes);
4375 } else {
4376 goto notsupported;
4378 } else if (bmpImage->green_mask==0x07e0) {
4379 if (bmpImage->blue_mask==0xf800) {
4380 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
4381 X11DRV_DIB_Convert_565_to_0888_asis
4382 (dstwidth,lines,
4383 srcbits,-bmpImage->bytes_per_line,
4384 dstbits,linebytes);
4385 } else if (bmpImage->red_mask==0xf800) {
4386 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
4387 X11DRV_DIB_Convert_565_to_0888_reverse
4388 (dstwidth,lines,
4389 srcbits,-bmpImage->bytes_per_line,
4390 dstbits,linebytes);
4391 } else {
4392 goto notsupported;
4394 } else {
4395 goto notsupported;
4397 } else {
4398 if (bmpImage->green_mask==0x03e0 &&
4399 (bmpImage->red_mask==0x7f00 ||
4400 bmpImage->blue_mask==0x7f00)) {
4401 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
4402 X11DRV_DIB_Convert_5x5_to_any0888
4403 (dstwidth,lines,
4404 srcbits,-bmpImage->bytes_per_line,
4405 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4406 dstbits,linebytes,
4407 rDst,gDst,bDst);
4408 } else if (bmpImage->green_mask==0x07e0 &&
4409 (bmpImage->red_mask==0xf800 ||
4410 bmpImage->blue_mask==0xf800)) {
4411 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
4412 X11DRV_DIB_Convert_5x5_to_any0888
4413 (dstwidth,lines,
4414 srcbits,-bmpImage->bytes_per_line,
4415 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4416 dstbits,linebytes,
4417 rDst,gDst,bDst);
4418 } else {
4419 goto notsupported;
4423 break;
4425 case 1:
4426 case 4:
4427 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4428 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
4429 int rShift,gShift,bShift;
4430 DWORD* dstpixel;
4432 rShift=X11DRV_DIB_MaskToShift(rDst);
4433 gShift=X11DRV_DIB_MaskToShift(gDst);
4434 bShift=X11DRV_DIB_MaskToShift(bDst);
4435 for (h = lines - 1; h >= 0; h--) {
4436 dstpixel=(DWORD*)dstbits;
4437 for (x = 0; x < dstwidth; x++) {
4438 PALETTEENTRY srcval;
4439 srcval = srccolors[XGetPixel(bmpImage, x, h)];
4440 *dstpixel++=(srcval.peRed << rShift) |
4441 (srcval.peGreen << gShift) |
4442 (srcval.peBlue << bShift);
4444 dstbits += linebytes;
4446 } else {
4447 goto notsupported;
4449 break;
4451 case 8:
4452 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4453 /* ==== pal 8 bmp -> any 0888 dib ==== */
4454 int rShift,gShift,bShift;
4455 const void* srcbits;
4456 const BYTE* srcpixel;
4457 DWORD* dstpixel;
4459 rShift=X11DRV_DIB_MaskToShift(rDst);
4460 gShift=X11DRV_DIB_MaskToShift(gDst);
4461 bShift=X11DRV_DIB_MaskToShift(bDst);
4462 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4463 for (h = lines - 1; h >= 0; h--) {
4464 srcpixel=srcbits;
4465 dstpixel=(DWORD*)dstbits;
4466 for (x = 0; x < dstwidth; x++) {
4467 PALETTEENTRY srcval;
4468 srcval=srccolors[(int)*srcpixel++];
4469 *dstpixel++=(srcval.peRed << rShift) |
4470 (srcval.peGreen << gShift) |
4471 (srcval.peBlue << bShift);
4473 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
4474 dstbits += linebytes;
4476 } else {
4477 goto notsupported;
4479 break;
4481 default:
4482 notsupported:
4484 /* ==== any bmp format -> any 0888 dib ==== */
4485 int rShift,gShift,bShift;
4486 DWORD* dstpixel;
4488 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
4489 bmpImage->depth, bmpImage->red_mask,
4490 bmpImage->green_mask, bmpImage->blue_mask,
4491 rDst,gDst,bDst);
4493 rShift=X11DRV_DIB_MaskToShift(rDst);
4494 gShift=X11DRV_DIB_MaskToShift(gDst);
4495 bShift=X11DRV_DIB_MaskToShift(bDst);
4496 for (h = lines - 1; h >= 0; h--) {
4497 dstpixel=(DWORD*)dstbits;
4498 for (x = 0; x < dstwidth; x++) {
4499 COLORREF srcval;
4500 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
4501 *dstpixel++=(GetRValue(srcval) << rShift) |
4502 (GetGValue(srcval) << gShift) |
4503 (GetBValue(srcval) << bShift);
4505 dstbits += linebytes;
4508 break;
4512 /***********************************************************************
4513 * X11DRV_DIB_SetImageBits
4515 * Transfer the bits to an X image.
4516 * Helper function for SetDIBits() and SetDIBitsToDevice().
4518 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4520 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4521 XImage *bmpImage;
4523 wine_tsx11_lock();
4524 if (descr->image)
4525 bmpImage = descr->image;
4526 else {
4527 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4528 descr->infoWidth, lines, 32, 0 );
4529 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4530 if(bmpImage->data == NULL) {
4531 ERR("Out of memory!\n");
4532 XDestroyImage( bmpImage );
4533 wine_tsx11_unlock();
4534 return lines;
4538 TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
4539 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4540 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
4541 bmpImage->depth,bmpImage->bits_per_pixel,
4542 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4544 /* Transfer the pixels */
4545 switch(descr->infoBpp)
4547 case 1:
4548 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
4549 descr->width, descr->xSrc, (int *)(descr->colorMap),
4550 bmpImage, descr->dibpitch );
4551 break;
4552 case 4:
4553 if (descr->compression) {
4554 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4555 descr->width, descr->height, AllPlanes, ZPixmap,
4556 bmpImage, descr->xSrc, descr->ySrc );
4558 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
4559 descr->infoWidth, descr->width,
4560 descr->xSrc, (int *)(descr->colorMap),
4561 bmpImage );
4562 } else
4563 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
4564 descr->infoWidth, descr->width,
4565 descr->xSrc, (int*)(descr->colorMap),
4566 bmpImage, descr->dibpitch );
4567 break;
4568 case 8:
4569 if (descr->compression) {
4570 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4571 descr->width, descr->height, AllPlanes, ZPixmap,
4572 bmpImage, descr->xSrc, descr->ySrc );
4573 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
4574 descr->infoWidth, descr->width,
4575 descr->xSrc, (int *)(descr->colorMap),
4576 bmpImage );
4577 } else
4578 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
4579 descr->infoWidth, descr->width,
4580 descr->xSrc, (int *)(descr->colorMap),
4581 bmpImage, descr->dibpitch );
4582 break;
4583 case 15:
4584 case 16:
4585 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
4586 descr->infoWidth, descr->width,
4587 descr->xSrc, descr->physDev,
4588 descr->rMask, descr->gMask, descr->bMask,
4589 bmpImage, descr->dibpitch);
4590 break;
4591 case 24:
4592 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
4593 descr->infoWidth, descr->width,
4594 descr->xSrc, descr->physDev,
4595 descr->rMask, descr->gMask, descr->bMask,
4596 bmpImage, descr->dibpitch);
4597 break;
4598 case 32:
4599 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
4600 descr->infoWidth, descr->width,
4601 descr->xSrc, descr->physDev,
4602 descr->rMask, descr->gMask, descr->bMask,
4603 bmpImage, descr->dibpitch);
4604 break;
4605 default:
4606 WARN("(%d): Invalid depth\n", descr->infoBpp );
4607 break;
4610 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
4611 descr->drawable, descr->gc, bmpImage,
4612 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4613 descr->width, descr->height);
4614 #ifdef HAVE_LIBXXSHM
4615 if (descr->useShm)
4617 XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4618 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4619 descr->width, descr->height, FALSE );
4620 XSync( gdi_display, 0 );
4622 else
4623 #endif
4624 XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4625 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4626 descr->width, descr->height );
4628 if (!descr->image) XDestroyImage( bmpImage );
4629 wine_tsx11_unlock();
4630 return lines;
4633 /***********************************************************************
4634 * X11DRV_DIB_GetImageBits
4636 * Transfer the bits from an X image.
4638 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4640 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4641 XImage *bmpImage;
4643 wine_tsx11_lock();
4644 if (descr->image)
4645 bmpImage = descr->image;
4646 else {
4647 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4648 descr->infoWidth, lines, 32, 0 );
4649 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4650 if(bmpImage->data == NULL) {
4651 ERR("Out of memory!\n");
4652 XDestroyImage( bmpImage );
4653 wine_tsx11_unlock();
4654 return lines;
4658 #ifdef HAVE_LIBXXSHM
4659 if (descr->useShm)
4661 int saveRed, saveGreen, saveBlue;
4663 TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
4664 gdi_display, descr->drawable, bmpImage,
4665 descr->xSrc, descr->ySrc, AllPlanes);
4667 /* We must save and restore the bmpImage's masks in order
4668 * to preserve them across the call to XShmGetImage, which
4669 * decides to eleminate them since it doesn't happen to know
4670 * what the format of the image is supposed to be, even though
4671 * we do. */
4672 saveRed = bmpImage->red_mask;
4673 saveBlue= bmpImage->blue_mask;
4674 saveGreen = bmpImage->green_mask;
4676 XShmGetImage( gdi_display, descr->drawable, bmpImage,
4677 descr->xSrc, descr->ySrc, AllPlanes);
4679 bmpImage->red_mask = saveRed;
4680 bmpImage->blue_mask = saveBlue;
4681 bmpImage->green_mask = saveGreen;
4683 else
4684 #endif /* HAVE_LIBXXSHM */
4686 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
4687 gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
4688 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
4689 XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
4690 descr->width, lines, AllPlanes, ZPixmap,
4691 bmpImage, descr->xDest, descr->yDest );
4694 TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
4695 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4696 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
4697 bmpImage->depth,bmpImage->bits_per_pixel,
4698 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4699 /* Transfer the pixels */
4700 switch(descr->infoBpp)
4702 case 1:
4703 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
4704 descr->infoWidth, descr->width,
4705 descr->colorMap, descr->palentry,
4706 bmpImage, descr->dibpitch );
4707 break;
4709 case 4:
4710 if (descr->compression)
4711 FIXME("Compression not yet supported!\n");
4712 else
4713 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
4714 descr->infoWidth, descr->width,
4715 descr->colorMap, descr->palentry,
4716 bmpImage, descr->dibpitch );
4717 break;
4719 case 8:
4720 if (descr->compression)
4721 FIXME("Compression not yet supported!\n");
4722 else
4723 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
4724 descr->infoWidth, descr->width,
4725 descr->colorMap, descr->palentry,
4726 bmpImage, descr->dibpitch );
4727 break;
4728 case 15:
4729 case 16:
4730 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
4731 descr->infoWidth,descr->width,
4732 descr->palentry,
4733 descr->rMask, descr->gMask, descr->bMask,
4734 bmpImage, descr->dibpitch );
4735 break;
4737 case 24:
4738 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
4739 descr->infoWidth,descr->width,
4740 descr->palentry,
4741 descr->rMask, descr->gMask, descr->bMask,
4742 bmpImage, descr->dibpitch);
4743 break;
4745 case 32:
4746 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
4747 descr->infoWidth, descr->width,
4748 descr->palentry,
4749 descr->rMask, descr->gMask, descr->bMask,
4750 bmpImage, descr->dibpitch);
4751 break;
4753 default:
4754 WARN("(%d): Invalid depth\n", descr->infoBpp );
4755 break;
4758 if (!descr->image) XDestroyImage( bmpImage );
4759 wine_tsx11_unlock();
4760 return lines;
4763 /*************************************************************************
4764 * X11DRV_SetDIBitsToDevice
4767 INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWORD cx,
4768 DWORD cy, INT xSrc, INT ySrc,
4769 UINT startscan, UINT lines, LPCVOID bits,
4770 const BITMAPINFO *info, UINT coloruse )
4772 X11DRV_DIB_IMAGEBITS_DESCR descr;
4773 DWORD width;
4774 INT result;
4775 int height;
4776 BOOL top_down;
4777 POINT pt;
4778 DC *dc = physDev->dc;
4780 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
4781 &descr.infoBpp, &descr.compression ) == -1)
4782 return 0;
4783 top_down = (height < 0);
4784 if (top_down) height = -height;
4786 pt.x = xDest;
4787 pt.y = yDest;
4788 LPtoDP(physDev->hdc, &pt, 1);
4790 if (!lines || (startscan >= height)) return 0;
4791 if (!top_down && startscan + lines > height) lines = height - startscan;
4793 /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
4794 * and clamp all values to fit inside [startscan,startscan+lines]
4796 if (ySrc + cy <= startscan + lines)
4798 INT y = startscan + lines - (ySrc + cy);
4799 if (ySrc < startscan) cy -= (startscan - ySrc);
4800 if (!top_down)
4802 /* avoid getting unnecessary lines */
4803 ySrc = 0;
4804 if (y >= lines) return 0;
4805 lines -= y;
4807 else
4809 if (y >= lines) return lines;
4810 ySrc = y; /* need to get all lines in top down mode */
4813 else
4815 if (ySrc >= startscan + lines) return lines;
4816 pt.y += ySrc + cy - (startscan + lines);
4817 cy = startscan + lines - ySrc;
4818 ySrc = 0;
4819 if (cy > lines) cy = lines;
4821 if (xSrc >= width) return lines;
4822 if (xSrc + cx >= width) cx = width - xSrc;
4823 if (!cx || !cy) return lines;
4825 X11DRV_SetupGCForText( physDev ); /* To have the correct colors */
4826 TSXSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
4828 switch (descr.infoBpp)
4830 case 1:
4831 case 4:
4832 case 8:
4833 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4834 coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
4835 dc->bitsPerPixel, info, &descr.nColorMap );
4836 if (!descr.colorMap) return 0;
4837 descr.rMask = descr.gMask = descr.bMask = 0;
4838 break;
4839 case 15:
4840 case 16:
4841 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4842 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4843 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4844 descr.colorMap = 0;
4845 break;
4847 case 24:
4848 case 32:
4849 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
4850 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4851 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4852 descr.colorMap = 0;
4853 break;
4856 descr.physDev = physDev;
4857 descr.bits = bits;
4858 descr.image = NULL;
4859 descr.palentry = NULL;
4860 descr.lines = top_down ? -lines : lines;
4861 descr.infoWidth = width;
4862 descr.depth = dc->bitsPerPixel;
4863 descr.drawable = physDev->drawable;
4864 descr.gc = physDev->gc;
4865 descr.xSrc = xSrc;
4866 descr.ySrc = ySrc;
4867 descr.xDest = physDev->org.x + pt.x;
4868 descr.yDest = physDev->org.y + pt.y;
4869 descr.width = cx;
4870 descr.height = cy;
4871 descr.useShm = FALSE;
4872 descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
4874 result = X11DRV_DIB_SetImageBits( &descr );
4876 if (descr.infoBpp <= 8)
4877 HeapFree(GetProcessHeap(), 0, descr.colorMap);
4878 return result;
4881 /***********************************************************************
4882 * SetDIBits (X11DRV.@)
4884 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
4885 UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
4887 X11DRV_DIB_IMAGEBITS_DESCR descr;
4888 BITMAPOBJ *bmp;
4889 int height, tmpheight;
4890 INT result;
4892 descr.physDev = physDev;
4894 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
4895 &descr.infoBpp, &descr.compression ) == -1)
4896 return 0;
4898 tmpheight = height;
4899 if (height < 0) height = -height;
4900 if (!lines || (startscan >= height))
4901 return 0;
4903 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
4905 if (startscan + lines > height) lines = height - startscan;
4907 switch (descr.infoBpp)
4909 case 1:
4910 case 4:
4911 case 8:
4912 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4913 coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
4914 bmp->bitmap.bmBitsPixel,
4915 info, &descr.nColorMap );
4916 if (!descr.colorMap)
4918 GDI_ReleaseObj( hbitmap );
4919 return 0;
4921 descr.rMask = descr.gMask = descr.bMask = 0;
4922 break;
4923 case 15:
4924 case 16:
4925 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4926 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4927 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4928 descr.colorMap = 0;
4929 break;
4931 case 24:
4932 case 32:
4933 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
4934 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4935 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4936 descr.colorMap = 0;
4937 break;
4939 default: break;
4942 descr.bits = bits;
4943 descr.image = NULL;
4944 descr.palentry = NULL;
4945 descr.lines = tmpheight >= 0 ? lines : -lines;
4946 descr.depth = bmp->bitmap.bmBitsPixel;
4947 descr.drawable = (Pixmap)bmp->physBitmap;
4948 descr.gc = BITMAP_GC(bmp);
4949 descr.xSrc = 0;
4950 descr.ySrc = 0;
4951 descr.xDest = 0;
4952 descr.yDest = height - startscan - lines;
4953 descr.width = bmp->bitmap.bmWidth;
4954 descr.height = lines;
4955 descr.useShm = FALSE;
4956 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
4957 X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
4958 result = X11DRV_DIB_SetImageBits( &descr );
4959 X11DRV_DIB_Unlock(bmp, TRUE);
4961 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
4963 GDI_ReleaseObj( hbitmap );
4964 return result;
4967 /***********************************************************************
4968 * GetDIBits (X11DRV.@)
4970 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
4971 LPVOID bits, BITMAPINFO *info, UINT coloruse )
4973 X11DRV_DIBSECTION *dib;
4974 X11DRV_DIB_IMAGEBITS_DESCR descr;
4975 PALETTEOBJ * palette;
4976 BITMAPOBJ *bmp;
4977 int height;
4978 DC *dc = physDev->dc;
4980 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
4981 return 0;
4982 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
4984 GDI_ReleaseObj( dc->hPalette );
4985 return 0;
4987 dib = (X11DRV_DIBSECTION *) bmp->dib;
4989 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
4990 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
4991 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
4992 startscan );
4994 if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
4996 height = info->bmiHeader.biHeight;
4997 if (height < 0) height = -height;
4998 if( lines > height ) lines = height;
4999 /* Top-down images have a negative biHeight, the scanlines of theses images
5000 * were inverted in X11DRV_DIB_GetImageBits_xx
5001 * To prevent this we simply change the sign of lines
5002 * (the number of scan lines to copy).
5003 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
5005 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
5007 if( startscan >= bmp->bitmap.bmHeight )
5009 lines = 0;
5010 goto done;
5013 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
5014 &descr.infoBpp, &descr.compression ) == -1)
5016 lines = 0;
5017 goto done;
5020 switch (descr.infoBpp)
5022 case 1:
5023 case 4:
5024 case 8:
5025 descr.rMask= descr.gMask = descr.bMask = 0;
5026 break;
5027 case 15:
5028 case 16:
5029 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
5030 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
5031 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
5032 break;
5033 case 24:
5034 case 32:
5035 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
5036 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
5037 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
5038 break;
5041 descr.physDev = physDev;
5042 descr.palentry = palette->logpalette.palPalEntry;
5043 descr.bits = bits;
5044 descr.image = NULL;
5045 descr.lines = lines;
5046 descr.depth = bmp->bitmap.bmBitsPixel;
5047 descr.drawable = (Pixmap)bmp->physBitmap;
5048 descr.gc = BITMAP_GC(bmp);
5049 descr.width = bmp->bitmap.bmWidth;
5050 descr.height = bmp->bitmap.bmHeight;
5051 descr.colorMap = info->bmiColors;
5052 descr.xDest = 0;
5053 descr.yDest = 0;
5054 descr.xSrc = 0;
5056 if (descr.lines > 0)
5058 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
5060 else
5062 descr.ySrc = startscan;
5064 #ifdef HAVE_LIBXXSHM
5065 descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
5066 #else
5067 descr.useShm = FALSE;
5068 #endif
5069 descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
5070 : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
5072 X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
5073 X11DRV_DIB_GetImageBits( &descr );
5074 X11DRV_DIB_Unlock(bmp, TRUE);
5076 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
5077 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
5078 info->bmiHeader.biWidth,
5079 info->bmiHeader.biHeight,
5080 info->bmiHeader.biBitCount );
5082 if (descr.compression == BI_BITFIELDS)
5084 *(DWORD *)info->bmiColors = descr.rMask;
5085 *((DWORD *)info->bmiColors+1) = descr.gMask;
5086 *((DWORD *)info->bmiColors+2) = descr.bMask;
5088 else
5090 /* if RLE or JPEG compression were supported,
5091 * this line would be invalid. */
5092 info->bmiHeader.biCompression = 0;
5095 done:
5096 GDI_ReleaseObj( dc->hPalette );
5097 GDI_ReleaseObj( hbitmap );
5098 return lines;
5101 /***********************************************************************
5102 * DIB_DoProtectDIBSection
5104 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
5106 DIBSECTION *dib = bmp->dib;
5107 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
5108 : -dib->dsBm.bmHeight;
5109 /* use the biSizeImage data as the memory size only if we're dealing with a
5110 compressed image where the value is set. Otherwise, calculate based on
5111 width * height */
5112 INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
5113 ? dib->dsBmih.biSizeImage
5114 : dib->dsBm.bmWidthBytes * effHeight;
5115 DWORD old_prot;
5117 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
5118 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
5121 /***********************************************************************
5122 * X11DRV_DIB_DoUpdateDIBSection
5124 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
5125 void *colorMap, int nColorMap,
5126 Drawable dest,
5127 DWORD xSrc, DWORD ySrc,
5128 DWORD xDest, DWORD yDest,
5129 DWORD width, DWORD height)
5131 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5132 X11DRV_DIB_IMAGEBITS_DESCR descr;
5134 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
5135 &descr.infoBpp, &descr.compression ) == -1)
5136 return;
5138 descr.physDev = NULL;
5139 descr.palentry = NULL;
5140 descr.image = dib->image;
5141 descr.colorMap = colorMap;
5142 descr.nColorMap = nColorMap;
5143 descr.bits = dib->dibSection.dsBm.bmBits;
5144 descr.depth = bmp->bitmap.bmBitsPixel;
5146 switch (descr.infoBpp)
5148 case 1:
5149 case 4:
5150 case 8:
5151 descr.rMask = descr.gMask = descr.bMask = 0;
5152 break;
5153 case 15:
5154 case 16:
5155 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
5156 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
5157 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
5158 break;
5160 case 24:
5161 case 32:
5162 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff0000;
5163 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x00ff00;
5164 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x0000ff;
5165 break;
5168 /* Hack for now */
5169 descr.drawable = dest;
5170 descr.gc = BITMAP_GC(bmp);
5171 descr.xSrc = xSrc;
5172 descr.ySrc = ySrc;
5173 descr.xDest = xDest;
5174 descr.yDest = yDest;
5175 descr.width = width;
5176 descr.height = height;
5177 #ifdef HAVE_LIBXXSHM
5178 descr.useShm = (dib->shminfo.shmid != -1);
5179 #else
5180 descr.useShm = FALSE;
5181 #endif
5182 descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
5184 if (toDIB)
5186 TRACE("Copying from Pixmap to DIB bits\n");
5187 X11DRV_DIB_GetImageBits( &descr );
5189 else
5191 TRACE("Copying from DIB bits to Pixmap\n");
5192 X11DRV_DIB_SetImageBits( &descr );
5196 /***********************************************************************
5197 * X11DRV_DIB_CopyDIBSection
5199 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
5200 DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
5201 DWORD width, DWORD height)
5203 BITMAPOBJ *bmp;
5204 DC *dcSrc = physDevSrc->dc;
5205 DC *dcDst = physDevDst->dc;
5206 int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
5208 TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", dcSrc, dcDst,
5209 xSrc, ySrc, xDest, yDest, width, height);
5210 /* this function is meant as an optimization for BitBlt,
5211 * not to be called otherwise */
5212 if (GetObjectType( physDevSrc->hdc ) != OBJ_MEMDC) {
5213 ERR("called for non-memory source DC!?\n");
5214 return;
5217 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
5218 if (!(bmp && bmp->dib)) {
5219 ERR("called for non-DIBSection!?\n");
5220 GDI_ReleaseObj( dcSrc->hBitmap );
5221 return;
5223 /* while BitBlt should already have made sure we only get
5224 * positive values, we should check for oversize values */
5225 if ((xSrc < bmp->bitmap.bmWidth) &&
5226 (ySrc < bmp->bitmap.bmHeight)) {
5227 if (xSrc + width > bmp->bitmap.bmWidth)
5228 width = bmp->bitmap.bmWidth - xSrc;
5229 if (ySrc + height > bmp->bitmap.bmHeight)
5230 height = bmp->bitmap.bmHeight - ySrc;
5231 /* if the source bitmap is 8bpp or less, we're supposed to use the
5232 * DC's palette for color conversion (not the DIB color table) */
5233 if (bmp->dib->dsBm.bmBitsPixel <= 8) {
5234 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5235 if ((!dcSrc->hPalette) ||
5236 (dcSrc->hPalette == GetStockObject(DEFAULT_PALETTE))) {
5237 /* HACK: no palette has been set in the source DC,
5238 * use the DIB colormap instead - this is necessary in some
5239 * cases since we need to do depth conversion in some places
5240 * where real Windows can just copy data straight over */
5241 colorMap = dib->colorMap;
5242 nColorMap = dib->nColorMap;
5243 } else {
5244 colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
5245 bmp->dib->dsBm.bmBitsPixel,
5246 (BITMAPINFO*)&(bmp->dib->dsBmih),
5247 &nColorMap );
5248 if (colorMap) aColorMap = TRUE;
5251 /* perform the copy */
5252 X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
5253 physDevDst->drawable, xSrc, ySrc,
5254 physDevDst->org.x + xDest, physDevDst->org.y + yDest,
5255 width, height);
5256 /* free color mapping */
5257 if (aColorMap)
5258 HeapFree(GetProcessHeap(), 0, colorMap);
5260 GDI_ReleaseObj( dcSrc->hBitmap );
5263 /***********************************************************************
5264 * X11DRV_DIB_DoUpdateDIBSection
5266 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
5268 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5269 X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
5270 (Drawable)bmp->physBitmap, 0, 0, 0, 0,
5271 bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
5274 /***********************************************************************
5275 * X11DRV_DIB_FaultHandler
5277 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
5279 BITMAPOBJ *bmp;
5280 INT state;
5282 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
5283 if (!bmp) return FALSE;
5285 state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
5286 if (state != DIB_Status_InSync) {
5287 /* no way to tell whether app needs read or write yet,
5288 * try read first */
5289 X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
5290 } else {
5291 /* hm, apparently the app must have write access */
5292 X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
5294 X11DRV_DIB_Unlock(bmp, TRUE);
5296 GDI_ReleaseObj( (HBITMAP)res );
5297 return TRUE;
5300 /***********************************************************************
5301 * X11DRV_DIB_Coerce
5303 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
5305 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5306 INT ret = DIB_Status_None;
5308 if (dib) {
5309 EnterCriticalSection(&(dib->lock));
5310 ret = dib->status;
5311 switch (req) {
5312 case DIB_Status_GdiMod:
5313 /* GDI access - request to draw on pixmap */
5314 switch (dib->status)
5316 default:
5317 case DIB_Status_None:
5318 dib->p_status = DIB_Status_GdiMod;
5319 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5320 break;
5322 case DIB_Status_GdiMod:
5323 TRACE("GdiMod requested in status GdiMod\n" );
5324 break;
5326 case DIB_Status_InSync:
5327 TRACE("GdiMod requested in status InSync\n" );
5328 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5329 dib->status = DIB_Status_GdiMod;
5330 dib->p_status = DIB_Status_InSync;
5331 break;
5333 case DIB_Status_AuxMod:
5334 TRACE("GdiMod requested in status AuxMod\n" );
5335 if (lossy) dib->status = DIB_Status_GdiMod;
5336 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
5337 dib->p_status = DIB_Status_AuxMod;
5338 if (dib->status != DIB_Status_AppMod) {
5339 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5340 break;
5342 /* fall through if copy_aux() had to change to AppMod state */
5344 case DIB_Status_AppMod:
5345 TRACE("GdiMod requested in status AppMod\n" );
5346 if (!lossy) {
5347 /* make it readonly to avoid app changing data while we copy */
5348 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5349 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5351 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5352 dib->p_status = DIB_Status_AppMod;
5353 dib->status = DIB_Status_GdiMod;
5354 break;
5356 break;
5358 case DIB_Status_InSync:
5359 /* App access - request access to read DIB surface */
5360 /* (typically called from signal handler) */
5361 switch (dib->status)
5363 default:
5364 case DIB_Status_None:
5365 /* shouldn't happen from signal handler */
5366 break;
5368 case DIB_Status_AuxMod:
5369 TRACE("InSync requested in status AuxMod\n" );
5370 if (lossy) dib->status = DIB_Status_InSync;
5371 else {
5372 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5373 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
5375 if (dib->status != DIB_Status_GdiMod) {
5376 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5377 break;
5379 /* fall through if copy_aux() had to change to GdiMod state */
5381 case DIB_Status_GdiMod:
5382 TRACE("InSync requested in status GdiMod\n" );
5383 if (!lossy) {
5384 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5385 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5387 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5388 dib->status = DIB_Status_InSync;
5389 break;
5391 case DIB_Status_InSync:
5392 TRACE("InSync requested in status InSync\n" );
5393 /* shouldn't happen from signal handler */
5394 break;
5396 case DIB_Status_AppMod:
5397 TRACE("InSync requested in status AppMod\n" );
5398 /* no reason to do anything here, and this
5399 * shouldn't happen from signal handler */
5400 break;
5402 break;
5404 case DIB_Status_AppMod:
5405 /* App access - request access to write DIB surface */
5406 /* (typically called from signal handler) */
5407 switch (dib->status)
5409 default:
5410 case DIB_Status_None:
5411 /* shouldn't happen from signal handler */
5412 break;
5414 case DIB_Status_AuxMod:
5415 TRACE("AppMod requested in status AuxMod\n" );
5416 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5417 if (lossy) dib->status = DIB_Status_AppMod;
5418 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5419 if (dib->status != DIB_Status_GdiMod)
5420 break;
5421 /* fall through if copy_aux() had to change to GdiMod state */
5423 case DIB_Status_GdiMod:
5424 TRACE("AppMod requested in status GdiMod\n" );
5425 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5426 if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5427 dib->status = DIB_Status_AppMod;
5428 break;
5430 case DIB_Status_InSync:
5431 TRACE("AppMod requested in status InSync\n" );
5432 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5433 dib->status = DIB_Status_AppMod;
5434 break;
5436 case DIB_Status_AppMod:
5437 TRACE("AppMod requested in status AppMod\n" );
5438 /* shouldn't happen from signal handler */
5439 break;
5441 break;
5443 case DIB_Status_AuxMod:
5444 if (dib->status == DIB_Status_None) {
5445 dib->p_status = req;
5446 } else {
5447 if (dib->status != DIB_Status_AuxMod)
5448 dib->p_status = dib->status;
5449 dib->status = DIB_Status_AuxMod;
5451 break;
5452 /* it is up to the caller to do the copy/conversion, probably
5453 * using the return value to decide where to copy from */
5455 LeaveCriticalSection(&(dib->lock));
5457 return ret;
5460 /***********************************************************************
5461 * X11DRV_DIB_Lock
5463 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
5465 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5466 INT ret = DIB_Status_None;
5468 if (dib) {
5469 TRACE("Locking %p from thread %04lx\n", bmp, GetCurrentThreadId());
5470 EnterCriticalSection(&(dib->lock));
5471 ret = dib->status;
5472 if (req != DIB_Status_None)
5473 X11DRV_DIB_Coerce(bmp, req, lossy);
5475 return ret;
5478 /***********************************************************************
5479 * X11DRV_DIB_Unlock
5481 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
5483 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5485 if (dib) {
5486 switch (dib->status)
5488 default:
5489 case DIB_Status_None:
5490 /* in case anyone is wondering, this is the "signal handler doesn't
5491 * work" case, where we always have to be ready for app access */
5492 if (commit) {
5493 switch (dib->p_status)
5495 case DIB_Status_AuxMod:
5496 TRACE("Unlocking and syncing from AuxMod\n" );
5497 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5498 if (dib->status != DIB_Status_None) {
5499 dib->p_status = dib->status;
5500 dib->status = DIB_Status_None;
5502 if (dib->p_status != DIB_Status_GdiMod)
5503 break;
5504 /* fall through if copy_aux() had to change to GdiMod state */
5506 case DIB_Status_GdiMod:
5507 TRACE("Unlocking and syncing from GdiMod\n" );
5508 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5509 break;
5511 default:
5512 TRACE("Unlocking without needing to sync\n" );
5513 break;
5516 else TRACE("Unlocking with no changes\n");
5517 dib->p_status = DIB_Status_None;
5518 break;
5520 case DIB_Status_GdiMod:
5521 TRACE("Unlocking in status GdiMod\n" );
5522 /* DIB was protected in Coerce */
5523 if (!commit) {
5524 /* no commit, revert to InSync if applicable */
5525 if ((dib->p_status == DIB_Status_InSync) ||
5526 (dib->p_status == DIB_Status_AppMod)) {
5527 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5528 dib->status = DIB_Status_InSync;
5531 break;
5533 case DIB_Status_InSync:
5534 TRACE("Unlocking in status InSync\n" );
5535 /* DIB was already protected in Coerce */
5536 break;
5538 case DIB_Status_AppMod:
5539 TRACE("Unlocking in status AppMod\n" );
5540 /* DIB was already protected in Coerce */
5541 /* this case is ordinary only called from the signal handler,
5542 * so we don't bother to check for !commit */
5543 break;
5545 case DIB_Status_AuxMod:
5546 TRACE("Unlocking in status AuxMod\n" );
5547 if (commit) {
5548 /* DIB may need protection now */
5549 if ((dib->p_status == DIB_Status_InSync) ||
5550 (dib->p_status == DIB_Status_AppMod))
5551 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5552 } else {
5553 /* no commit, revert to previous state */
5554 if (dib->p_status != DIB_Status_None)
5555 dib->status = dib->p_status;
5556 /* no protections changed */
5558 dib->p_status = DIB_Status_None;
5559 break;
5561 LeaveCriticalSection(&(dib->lock));
5562 TRACE("Unlocked %p\n", bmp);
5566 /***********************************************************************
5567 * X11DRV_CoerceDIBSection2
5569 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5571 BITMAPOBJ *bmp;
5572 INT ret;
5574 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5575 if (!bmp) return DIB_Status_None;
5576 ret = X11DRV_DIB_Coerce(bmp, req, lossy);
5577 GDI_ReleaseObj( hBmp );
5578 return ret;
5581 /***********************************************************************
5582 * X11DRV_LockDIBSection2
5584 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5586 BITMAPOBJ *bmp;
5587 INT ret;
5589 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5590 if (!bmp) return DIB_Status_None;
5591 ret = X11DRV_DIB_Lock(bmp, req, lossy);
5592 GDI_ReleaseObj( hBmp );
5593 return ret;
5596 /***********************************************************************
5597 * X11DRV_UnlockDIBSection2
5599 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
5601 BITMAPOBJ *bmp;
5603 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5604 if (!bmp) return;
5605 X11DRV_DIB_Unlock(bmp, commit);
5606 GDI_ReleaseObj( hBmp );
5609 /***********************************************************************
5610 * X11DRV_CoerceDIBSection
5612 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
5614 if (!physDev) return DIB_Status_None;
5615 return X11DRV_CoerceDIBSection2( physDev->dc->hBitmap, req, lossy );
5618 /***********************************************************************
5619 * X11DRV_LockDIBSection
5621 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
5623 if (!physDev) return DIB_Status_None;
5624 if (GetObjectType( physDev->hdc ) != OBJ_MEMDC) return DIB_Status_None;
5626 return X11DRV_LockDIBSection2( physDev->dc->hBitmap, req, lossy );
5629 /***********************************************************************
5630 * X11DRV_UnlockDIBSection
5632 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
5634 if (!physDev) return;
5635 if (GetObjectType( physDev->hdc ) != OBJ_MEMDC) return;
5637 X11DRV_UnlockDIBSection2( physDev->dc->hBitmap, commit );
5641 #ifdef HAVE_LIBXXSHM
5642 /***********************************************************************
5643 * X11DRV_XShmErrorHandler
5646 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
5648 return 1; /* FIXME: should check event contents */
5651 /***********************************************************************
5652 * X11DRV_XShmCreateImage
5655 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
5656 XShmSegmentInfo* shminfo)
5658 XImage *image;
5660 image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
5661 if (image)
5663 shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
5664 IPC_CREAT|0700);
5665 if( shminfo->shmid != -1 )
5667 shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
5668 if( shminfo->shmaddr != (char*)-1 )
5670 BOOL ok;
5672 shminfo->readOnly = FALSE;
5673 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
5674 ok = (XShmAttach( gdi_display, shminfo ) != 0);
5675 if (X11DRV_check_error()) ok = FALSE;
5676 if (ok)
5678 shmctl(shminfo->shmid, IPC_RMID, 0);
5679 return image; /* Success! */
5681 /* An error occured */
5682 shmdt(shminfo->shmaddr);
5684 shmctl(shminfo->shmid, IPC_RMID, 0);
5686 XFlush(gdi_display);
5687 XDestroyImage(image);
5688 image = NULL;
5690 return image;
5692 #endif /* HAVE_LIBXXSHM */
5695 /***********************************************************************
5696 * X11DRV_DIB_CreateDIBSection
5698 HBITMAP X11DRV_DIB_CreateDIBSection(
5699 X11DRV_PDEVICE *physDev, BITMAPINFO *bmi, UINT usage,
5700 LPVOID *bits, HANDLE section,
5701 DWORD offset, DWORD ovr_pitch)
5703 HBITMAP res = 0;
5704 BITMAPOBJ *bmp = NULL;
5705 X11DRV_DIBSECTION *dib = NULL;
5706 int *colorMap = NULL;
5707 int nColorMap;
5709 /* Fill BITMAP32 structure with DIB data */
5710 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
5711 INT effHeight, totalSize;
5712 BITMAP bm;
5713 LPVOID mapBits = NULL;
5715 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
5716 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
5717 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
5719 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
5720 bm.bmType = 0;
5721 bm.bmWidth = bi->biWidth;
5722 bm.bmHeight = effHeight;
5723 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
5724 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
5725 bm.bmPlanes = bi->biPlanes;
5726 bm.bmBitsPixel = bi->biBitCount;
5727 bm.bmBits = NULL;
5729 /* Get storage location for DIB bits. Only use biSizeImage if it's valid and
5730 we're dealing with a compressed bitmap. Otherwise, use width * height. */
5731 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
5732 ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
5734 if (section)
5736 SYSTEM_INFO SystemInfo;
5737 DWORD mapOffset;
5738 INT mapSize;
5740 GetSystemInfo( &SystemInfo );
5741 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
5742 mapSize = totalSize + (offset - mapOffset);
5743 mapBits = MapViewOfFile( section,
5744 FILE_MAP_ALL_ACCESS,
5746 mapOffset,
5747 mapSize );
5748 bm.bmBits = (char *)mapBits + (offset - mapOffset);
5750 else if (ovr_pitch && offset)
5751 bm.bmBits = (LPVOID) offset;
5752 else {
5753 offset = 0;
5754 bm.bmBits = VirtualAlloc(NULL, totalSize,
5755 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
5758 /* Create Color Map */
5759 if (bm.bmBits && bm.bmBitsPixel <= 8)
5760 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? physDev : NULL,
5761 usage, bm.bmBitsPixel, bmi, &nColorMap );
5763 /* Allocate Memory for DIB and fill structure */
5764 if (bm.bmBits)
5765 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
5766 if (dib)
5768 dib->dibSection.dsBm = bm;
5769 dib->dibSection.dsBmih = *bi;
5770 dib->dibSection.dsBmih.biSizeImage = totalSize;
5772 /* Set dsBitfields values */
5773 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
5775 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
5777 else switch( bi->biBitCount )
5779 case 15:
5780 case 16:
5781 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
5782 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
5783 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
5784 break;
5786 case 24:
5787 case 32:
5788 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff0000;
5789 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
5790 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
5791 break;
5793 dib->dibSection.dshSection = section;
5794 dib->dibSection.dsOffset = offset;
5796 dib->status = DIB_Status_None;
5797 dib->nColorMap = nColorMap;
5798 dib->colorMap = colorMap;
5801 /* Create Device Dependent Bitmap and add DIB pointer */
5802 if (dib)
5804 res = CreateDIBitmap(physDev->hdc, bi, 0, NULL, bmi, usage);
5805 if (res)
5807 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
5808 if (bmp) bmp->dib = (DIBSECTION *) dib;
5812 /* Create XImage */
5813 if (dib && bmp)
5815 wine_tsx11_lock();
5816 #ifdef HAVE_LIBXXSHM
5817 if (XShmQueryExtension(gdi_display) &&
5818 (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
5819 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
5821 ; /* Created Image */
5822 } else {
5823 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5824 dib->shminfo.shmid = -1;
5826 #else
5827 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5828 #endif
5829 wine_tsx11_unlock();
5832 /* Clean up in case of errors */
5833 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
5835 TRACE("got an error res=%p, bmp=%p, dib=%p, bm.bmBits=%p\n",
5836 res, bmp, dib, bm.bmBits);
5837 if (bm.bmBits)
5839 if (section)
5840 UnmapViewOfFile(mapBits), bm.bmBits = NULL;
5841 else if (!offset)
5842 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
5845 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
5846 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
5847 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
5848 if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
5849 if (res) { DeleteObject(res); res = 0; }
5851 else if (bm.bmBits)
5853 /* Install fault handler, if possible */
5854 InitializeCriticalSection(&(dib->lock));
5855 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
5857 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5858 if (dib) dib->status = DIB_Status_AppMod;
5862 /* Return BITMAP handle and storage location */
5863 if (bmp) GDI_ReleaseObj(res);
5864 if (bm.bmBits && bits) *bits = bm.bmBits;
5865 return res;
5868 /***********************************************************************
5869 * X11DRV_DIB_DeleteDIBSection
5871 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
5873 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5875 if (dib->image)
5877 wine_tsx11_lock();
5878 #ifdef HAVE_LIBXXSHM
5879 if (dib->shminfo.shmid != -1)
5881 XShmDetach (gdi_display, &(dib->shminfo));
5882 XDestroyImage (dib->image);
5883 shmdt (dib->shminfo.shmaddr);
5884 dib->shminfo.shmid = -1;
5886 else
5887 #endif
5888 XDestroyImage( dib->image );
5889 wine_tsx11_unlock();
5892 if (dib->colorMap)
5893 HeapFree(GetProcessHeap(), 0, dib->colorMap);
5895 DeleteCriticalSection(&(dib->lock));
5898 /***********************************************************************
5899 * SetDIBColorTable (X11DRV.@)
5901 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
5903 BITMAPOBJ * bmp;
5904 X11DRV_DIBSECTION *dib;
5905 UINT ret = 0;
5907 if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
5908 dib = (X11DRV_DIBSECTION *) bmp->dib;
5910 if (dib && dib->colorMap) {
5911 UINT end = count + start;
5912 if (end > dib->nColorMap) end = dib->nColorMap;
5914 * Changing color table might change the mapping between
5915 * DIB colors and X11 colors and thus alter the visible state
5916 * of the bitmap object.
5918 X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
5919 X11DRV_DIB_GenColorMap( physDev, dib->colorMap, DIB_RGB_COLORS,
5920 dib->dibSection.dsBm.bmBitsPixel,
5921 TRUE, colors, start, end );
5922 X11DRV_DIB_Unlock(bmp, TRUE);
5923 ret = end - start;
5925 GDI_ReleaseObj( physDev->dc->hBitmap );
5926 return ret;
5929 /***********************************************************************
5930 * GetDIBColorTable (X11DRV.@)
5932 UINT X11DRV_GetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, RGBQUAD *colors )
5934 BITMAPOBJ * bmp;
5935 X11DRV_DIBSECTION *dib;
5936 UINT ret = 0;
5938 if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
5939 dib = (X11DRV_DIBSECTION *) bmp->dib;
5941 if (dib && dib->colorMap) {
5942 UINT i, end = count + start;
5943 if (end > dib->nColorMap) end = dib->nColorMap;
5944 for (i = start; i < end; i++,colors++) {
5945 COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
5946 colors->rgbBlue = GetBValue(col);
5947 colors->rgbGreen = GetGValue(col);
5948 colors->rgbRed = GetRValue(col);
5949 colors->rgbReserved = 0;
5951 ret = end-start;
5953 GDI_ReleaseObj( physDev->dc->hBitmap );
5954 return ret;
5958 /**************************************************************************
5959 * X11DRV_DIB_CreateDIBFromPixmap
5961 * Allocates a packed DIB and copies the Pixmap data into it.
5962 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
5964 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
5966 HBITMAP hBmp = 0;
5967 BITMAPOBJ *pBmp = NULL;
5968 HGLOBAL hPackedDIB = 0;
5970 /* Allocates an HBITMAP which references the Pixmap passed to us */
5971 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
5972 if (!hBmp)
5974 TRACE("\tCould not create bitmap header for Pixmap\n");
5975 goto END;
5979 * Create a packed DIB from the Pixmap wrapper bitmap created above.
5980 * A packed DIB contains a BITMAPINFO structure followed immediately by
5981 * an optional color palette and the pixel data.
5983 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
5985 /* Get a pointer to the BITMAPOBJ structure */
5986 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5988 /* We can now get rid of the HBITMAP wrapper we created earlier.
5989 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
5991 if (!bDeletePixmap)
5993 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
5994 pBmp->physBitmap = NULL;
5995 pBmp->funcs = NULL;
5997 GDI_ReleaseObj( hBmp );
5998 DeleteObject(hBmp);
6000 END:
6001 TRACE("\tReturning packed DIB %p\n", hPackedDIB);
6002 return hPackedDIB;
6006 /**************************************************************************
6007 * X11DRV_DIB_CreatePixmapFromDIB
6009 * Creates a Pixmap from a packed DIB
6011 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
6013 Pixmap pixmap = None;
6014 HBITMAP hBmp = 0;
6015 BITMAPOBJ *pBmp = NULL;
6016 LPBYTE pPackedDIB = NULL;
6017 LPBITMAPINFO pbmi = NULL;
6018 LPBITMAPINFOHEADER pbmiHeader = NULL;
6019 LPBYTE pbits = NULL;
6021 /* Get a pointer to the packed DIB's data */
6022 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
6023 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
6024 pbmi = (LPBITMAPINFO)pPackedDIB;
6025 pbits = (LPBYTE)(pPackedDIB
6026 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
6028 /* Create a DDB from the DIB */
6030 hBmp = CreateDIBitmap(hdc,
6031 pbmiHeader,
6032 CBM_INIT,
6033 (LPVOID)pbits,
6034 pbmi,
6035 DIB_RGB_COLORS);
6037 GlobalUnlock(hPackedDIB);
6039 TRACE("CreateDIBitmap returned %p\n", hBmp);
6041 /* Retrieve the internal Pixmap from the DDB */
6043 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
6045 pixmap = (Pixmap)pBmp->physBitmap;
6046 /* clear the physBitmap so that we can steal its pixmap */
6047 pBmp->physBitmap = NULL;
6048 pBmp->funcs = NULL;
6050 /* Delete the DDB we created earlier now that we have stolen its pixmap */
6051 GDI_ReleaseObj( hBmp );
6052 DeleteObject(hBmp);
6054 TRACE("\tReturning Pixmap %ld\n", pixmap);
6055 return pixmap;