Correct Word breaking in centred/right justified mode; it was leaving a
[wine/dcerpc.git] / graphics / x11drv / dib.c
blob3d776a597b6cdf9e0bcdddf8f91c00ed028ee463
1 /*
2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
5 */
7 #include "config.h"
9 #include "ts_xlib.h"
10 #include "ts_xutil.h"
11 #ifdef HAVE_LIBXXSHM
12 # include "ts_xshm.h"
13 # ifdef HAVE_SYS_SHM_H
14 # include <sys/shm.h>
15 # endif
16 # ifdef HAVE_SYS_IPC_H
17 # include <sys/ipc.h>
18 # endif
19 #endif /* defined(HAVE_LIBXXSHM) */
21 #include <stdlib.h>
22 #include <string.h>
23 #include "windef.h"
24 #include "bitmap.h"
25 #include "x11drv.h"
26 #include "debugtools.h"
27 #include "gdi.h"
28 #include "palette.h"
29 #include "global.h"
31 DEFAULT_DEBUG_CHANNEL(bitmap);
32 DECLARE_DEBUG_CHANNEL(x11drv);
34 static int ximageDepthTable[32];
36 #ifdef HAVE_LIBXXSHM
37 static int XShmErrorFlag = 0;
38 #endif
40 /* This structure holds the arguments for DIB_SetImageBits() */
41 typedef struct
43 struct tagDC *dc;
44 LPCVOID bits;
45 XImage *image;
46 PALETTEENTRY *palentry;
47 int lines;
48 DWORD infoWidth;
49 WORD depth;
50 WORD infoBpp;
51 WORD compression;
52 RGBQUAD *colorMap;
53 int nColorMap;
54 Drawable drawable;
55 GC gc;
56 int xSrc;
57 int ySrc;
58 int xDest;
59 int yDest;
60 int width;
61 int height;
62 DWORD rMask;
63 DWORD gMask;
64 DWORD bMask;
65 BOOL useShm;
66 int dibpitch;
67 } X11DRV_DIB_IMAGEBITS_DESCR;
70 enum Rle_EscapeCodes
72 RLE_EOL = 0, /* End of line */
73 RLE_END = 1, /* End of bitmap */
74 RLE_DELTA = 2 /* Delta */
77 /***********************************************************************
78 * X11DRV_DIB_GetXImageWidthBytes
80 * Return the width of an X image in bytes
82 inline static int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
84 if (!depth || depth > 32) goto error;
86 if (!ximageDepthTable[depth-1])
88 XImage *testimage = XCreateImage( gdi_display, visual, depth,
89 ZPixmap, 0, NULL, 1, 1, 32, 20 );
90 if (testimage)
92 ximageDepthTable[depth-1] = testimage->bits_per_pixel;
93 XDestroyImage( testimage );
95 else ximageDepthTable[depth-1] = -1;
97 if (ximageDepthTable[depth-1] != -1)
98 return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
100 error:
101 WARN( "(%d): Unsupported depth\n", depth );
102 return 4 * width;
106 /***********************************************************************
107 * X11DRV_DIB_CreateXImage
109 * Create an X image.
111 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
113 int width_bytes;
114 XImage *image;
116 wine_tsx11_lock();
117 width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
118 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
119 calloc( height, width_bytes ),
120 width, height, 32, width_bytes );
121 wine_tsx11_unlock();
122 return image;
126 /***********************************************************************
127 * X11DRV_DIB_GenColorMap
129 * Fills the color map of a bitmap palette. Should not be called
130 * for a >8-bit deep bitmap.
132 int *X11DRV_DIB_GenColorMap( DC *dc, int *colorMapping,
133 WORD coloruse, WORD depth, BOOL quads,
134 const void *colorPtr, int start, int end )
136 int i;
138 if (coloruse == DIB_RGB_COLORS)
140 int max = 1 << depth;
142 if (end > max) end = max;
144 if (quads)
146 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
148 if (depth == 1) /* Monochrome */
149 for (i = start; i < end; i++, rgb++)
150 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
151 rgb->rgbBlue > 255*3/2);
152 else
153 for (i = start; i < end; i++, rgb++)
154 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbRed,
155 rgb->rgbGreen,
156 rgb->rgbBlue));
158 else
160 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
162 if (depth == 1) /* Monochrome */
163 for (i = start; i < end; i++, rgb++)
164 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
165 rgb->rgbtBlue > 255*3/2);
166 else
167 for (i = start; i < end; i++, rgb++)
168 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, RGB(rgb->rgbtRed,
169 rgb->rgbtGreen,
170 rgb->rgbtBlue));
173 else /* DIB_PAL_COLORS */
175 if (colorPtr) {
176 WORD * index = (WORD *)colorPtr;
178 for (i = start; i < end; i++, index++)
179 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(*index) );
180 } else {
181 for (i = start; i < end; i++)
182 colorMapping[i] = X11DRV_PALETTE_ToPhysical( dc, PALETTEINDEX(i) );
186 return colorMapping;
189 /***********************************************************************
190 * X11DRV_DIB_BuildColorMap
192 * Build the color map from the bitmap palette. Should not be called
193 * for a >8-bit deep bitmap.
195 int *X11DRV_DIB_BuildColorMap( DC *dc, WORD coloruse, WORD depth,
196 const BITMAPINFO *info, int *nColors )
198 int colors;
199 BOOL isInfo;
200 const void *colorPtr;
201 int *colorMapping;
203 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
205 colors = info->bmiHeader.biClrUsed;
206 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
207 colorPtr = info->bmiColors;
209 else /* assume BITMAPCOREINFO */
211 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
212 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
215 if (colors > 256)
217 ERR("called with >256 colors!\n");
218 return NULL;
221 /* just so CopyDIBSection doesn't have to create an identity palette */
222 if (coloruse == (WORD)-1) colorPtr = NULL;
224 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
225 colors * sizeof(int) )))
226 return NULL;
228 *nColors = colors;
229 return X11DRV_DIB_GenColorMap( dc, colorMapping, coloruse, depth,
230 isInfo, colorPtr, 0, colors);
234 /***********************************************************************
235 * X11DRV_DIB_MapColor
237 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
239 int color;
241 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
242 return oldcol;
244 for (color = 0; color < nPhysMap; color++)
245 if (physMap[color] == phys)
246 return color;
248 WARN("Strange color %08x\n", phys);
249 return 0;
253 /*********************************************************************
254 * X11DRV_DIB_GetNearestIndex
256 * Helper for X11DRV_DIB_GetDIBits.
257 * Returns the nearest colour table index for a given RGB.
258 * Nearest is defined by minimizing the sum of the squares.
260 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
262 INT i, best = -1, diff, bestdiff = -1;
263 RGBQUAD *color;
265 for(color = colormap, i = 0; i < numColors; color++, i++) {
266 diff = (r - color->rgbRed) * (r - color->rgbRed) +
267 (g - color->rgbGreen) * (g - color->rgbGreen) +
268 (b - color->rgbBlue) * (b - color->rgbBlue);
269 if(diff == 0)
270 return i;
271 if(best == -1 || diff < bestdiff) {
272 best = i;
273 bestdiff = diff;
276 return best;
278 /*********************************************************************
279 * X11DRV_DIB_MaskToShift
281 * Helper for X11DRV_DIB_GetDIBits.
282 * Returns the by how many bits to shift a given color so that it is
283 * in the proper position.
285 static INT X11DRV_DIB_MaskToShift(DWORD mask)
287 int shift;
289 if (mask==0)
290 return 0;
292 shift=0;
293 while ((mask&1)==0) {
294 mask>>=1;
295 shift++;
297 return shift;
300 /***********************************************************************
301 * X11DRV_DIB_Convert_any_asis
303 * All X11DRV_DIB_Convert_Xxx functions take at least the following
304 * parameters:
305 * - width
306 * This is the width in pixel of the surface to copy. This may be less
307 * than the full width of the image.
308 * - height
309 * The number of lines to copy. This may be less than the full height
310 * of the image. This is always >0.
311 * - srcbits
312 * Points to the first byte containing data to be copied. If the source
313 * surface starts are coordinates (x,y) then this is:
314 * image_ptr+x*bytes_pre_pixel+y*bytes_per_line
315 * (with further adjustments for top-down/bottom-up images)
316 * - srclinebytes
317 * This is the number of bytes per line. It may be >0 or <0 depending on
318 * whether this is a top-down or bottom-up image.
319 * - dstbits
320 * Same as srcbits but for the destination
321 * - dstlinebytes
322 * Same as srclinebytes but for the destination.
324 * Notes:
325 * - The supported Dib formats are: pal1, pal4, pal8, rgb555, bgr555,
326 * rgb565, bgr565, rgb888 and any 32bit (0888) format.
327 * The supported XImage (Bmp) formats are: pal1, pal4, pal8,
328 * rgb555, bgr555, rgb565, bgr565, rgb888, bgr888, rgb0888, bgr0888.
329 * - Rgb formats are those for which the masks are such that:
330 * red_mask > green_mask > blue_mask
331 * - Bgr formats are those for which the masks sort in the other direction.
332 * - Many conversion functions handle both rgb->bgr and bgr->rgb conversions
333 * so the comments use h, g, l to mean respectively the source color in the
334 * high bits, the green, and the source color in the low bits.
336 static void X11DRV_DIB_Convert_any_asis(int width, int height,
337 int bytes_per_pixel,
338 const void* srcbits, int srclinebytes,
339 void* dstbits, int dstlinebytes)
341 int y;
343 width*=bytes_per_pixel;
344 for (y=0; y<height; y++) {
345 memcpy(dstbits, srcbits, width);
346 srcbits += srclinebytes;
347 dstbits += dstlinebytes;
352 * 15 bit conversions
355 static void X11DRV_DIB_Convert_555_reverse(int width, int height,
356 const void* srcbits, int srclinebytes,
357 void* dstbits, int dstlinebytes)
359 const DWORD* srcpixel;
360 DWORD* dstpixel;
361 int x,y;
363 for (y=0; y<height; y++) {
364 srcpixel=srcbits;
365 dstpixel=dstbits;
366 for (x=0; x<width/2; x++) {
367 /* Do 2 pixels at a time */
368 DWORD srcval;
369 srcval=*srcpixel++;
370 *dstpixel++=((srcval << 10) & 0x7c007c00) | /* h */
371 ( srcval & 0x03e003e0) | /* g */
372 ((srcval >> 10) & 0x001f001f); /* l */
374 if (width&1) {
375 /* And the the odd pixel */
376 WORD srcval;
377 srcval=*((WORD*)srcpixel);
378 *((WORD*)dstpixel)=((srcval << 10) & 0x7c00) | /* h */
379 ( srcval & 0x03e0) | /* g */
380 ((srcval >> 10) & 0x001f); /* l */
382 srcbits += srclinebytes;
383 dstbits += dstlinebytes;
387 static void X11DRV_DIB_Convert_555_to_565_asis(int width, int height,
388 const void* srcbits, int srclinebytes,
389 void* dstbits, int dstlinebytes)
391 const DWORD* srcpixel;
392 DWORD* dstpixel;
393 int x,y;
395 for (y=0; y<height; y++) {
396 srcpixel=srcbits;
397 dstpixel=dstbits;
398 for (x=0; x<width/2; x++) {
399 /* Do 2 pixels at a time */
400 DWORD srcval;
401 srcval=*srcpixel++;
402 *dstpixel++=((srcval << 1) & 0xffc0ffc0) | /* h, g */
403 ((srcval >> 4) & 0x00200020) | /* g - 1 bit */
404 ( srcval & 0x001f001f); /* l */
406 if (width&1) {
407 /* And the the odd pixel */
408 WORD srcval;
409 srcval=*((WORD*)srcpixel);
410 *((WORD*)dstpixel)=((srcval << 1) & 0xffc0) | /* h, g */
411 ((srcval >> 4) & 0x0020) | /* g - 1 bit */
412 (srcval & 0x001f); /* l */
414 srcbits += srclinebytes;
415 dstbits += dstlinebytes;
419 static void X11DRV_DIB_Convert_555_to_565_reverse(int width, int height,
420 const void* srcbits, int srclinebytes,
421 void* dstbits, int dstlinebytes)
423 const DWORD* srcpixel;
424 DWORD* dstpixel;
425 int x,y;
427 for (y=0; y<height; y++) {
428 srcpixel=srcbits;
429 dstpixel=dstbits;
430 for (x=0; x<width/2; x++) {
431 /* Do 2 pixels at a time */
432 DWORD srcval;
433 srcval=*srcpixel++;
434 *dstpixel++=((srcval >> 10) & 0x001f001f) | /* h */
435 ((srcval << 1) & 0x07c007c0) | /* g */
436 ((srcval >> 4) & 0x00200020) | /* g - 1 bit */
437 ((srcval << 11) & 0xf800f800); /* l */
439 if (width&1) {
440 /* And the the odd pixel */
441 WORD srcval;
442 srcval=*((WORD*)srcpixel);
443 *((WORD*)dstpixel)=((srcval >> 10) & 0x001f) | /* h */
444 ((srcval << 1) & 0x07c0) | /* g */
445 ((srcval >> 4) & 0x0020) | /* g - 1 bit */
446 ((srcval << 11) & 0xf800); /* l */
448 srcbits += srclinebytes;
449 dstbits += dstlinebytes;
453 static void X11DRV_DIB_Convert_555_to_888_asis(int width, int height,
454 const void* srcbits, int srclinebytes,
455 void* dstbits, int dstlinebytes)
457 const WORD* srcpixel;
458 BYTE* dstpixel;
459 int x,y;
461 for (y=0; y<height; y++) {
462 srcpixel=srcbits;
463 dstpixel=dstbits;
464 for (x=0; x<width; x++) {
465 WORD srcval;
466 srcval=*srcpixel++;
467 dstpixel[0]=((srcval << 3) & 0xf8) | /* l */
468 ((srcval >> 2) & 0x07); /* l - 3 bits */
469 dstpixel[1]=((srcval >> 2) & 0xf8) | /* g */
470 ((srcval >> 7) & 0x07); /* g - 3 bits */
471 dstpixel[2]=((srcval >> 7) & 0xf8) | /* h */
472 ((srcval >> 12) & 0x07); /* h - 3 bits */
473 dstpixel+=3;
475 srcbits += srclinebytes;
476 dstbits += dstlinebytes;
480 static void X11DRV_DIB_Convert_555_to_888_reverse(int width, int height,
481 const void* srcbits, int srclinebytes,
482 void* dstbits, int dstlinebytes)
484 const WORD* srcpixel;
485 BYTE* dstpixel;
486 int x,y;
488 for (y=0; y<height; y++) {
489 srcpixel=srcbits;
490 dstpixel=dstbits;
491 for (x=0; x<width; x++) {
492 WORD srcval;
493 srcval=*srcpixel++;
494 dstpixel[0]=((srcval >> 7) & 0xf8) | /* h */
495 ((srcval >> 12) & 0x07); /* h - 3 bits */
496 dstpixel[1]=((srcval >> 2) & 0xf8) | /* g */
497 ((srcval >> 7) & 0x07); /* g - 3 bits */
498 dstpixel[2]=((srcval << 3) & 0xf8) | /* l */
499 ((srcval >> 2) & 0x07); /* l - 3 bits */
500 dstpixel+=3;
502 srcbits += srclinebytes;
503 dstbits += dstlinebytes;
507 static void X11DRV_DIB_Convert_555_to_0888_asis(int width, int height,
508 const void* srcbits, int srclinebytes,
509 void* dstbits, int dstlinebytes)
511 const WORD* srcpixel;
512 DWORD* dstpixel;
513 int x,y;
515 for (y=0; y<height; y++) {
516 srcpixel=srcbits;
517 dstpixel=dstbits;
518 for (x=0; x<width; x++) {
519 WORD srcval;
520 srcval=*srcpixel++;
521 *dstpixel++=((srcval << 9) & 0xf80000) | /* h */
522 ((srcval << 4) & 0x070000) | /* h - 3 bits */
523 ((srcval << 6) & 0x00f800) | /* g */
524 ((srcval << 1) & 0x000700) | /* g - 3 bits */
525 ((srcval << 3) & 0x0000f8) | /* l */
526 ((srcval >> 2) & 0x000007); /* l - 3 bits */
528 srcbits += srclinebytes;
529 dstbits += dstlinebytes;
533 static void X11DRV_DIB_Convert_555_to_0888_reverse(int width, int height,
534 const void* srcbits, int srclinebytes,
535 void* dstbits, int dstlinebytes)
537 const WORD* srcpixel;
538 DWORD* dstpixel;
539 int x,y;
541 for (y=0; y<height; y++) {
542 srcpixel=srcbits;
543 dstpixel=dstbits;
544 for (x=0; x<width; x++) {
545 WORD srcval;
546 srcval=*srcpixel++;
547 *dstpixel++=((srcval >> 7) & 0x0000f8) | /* h */
548 ((srcval >> 12) & 0x000007) | /* h - 3 bits */
549 ((srcval << 6) & 0x00f800) | /* g */
550 ((srcval << 1) & 0x000700) | /* g - 3 bits */
551 ((srcval << 19) & 0xf80000) | /* l */
552 ((srcval << 14) & 0x070000); /* l - 3 bits */
554 srcbits += srclinebytes;
555 dstbits += dstlinebytes;
559 static void X11DRV_DIB_Convert_5x5_to_any0888(int width, int height,
560 const void* srcbits, int srclinebytes,
561 WORD rsrc, WORD gsrc, WORD bsrc,
562 void* dstbits, int dstlinebytes,
563 DWORD rdst, DWORD gdst, DWORD bdst)
565 int rRightShift1,gRightShift1,bRightShift1;
566 int rRightShift2,gRightShift2,bRightShift2;
567 BYTE gMask1,gMask2;
568 int rLeftShift,gLeftShift,bLeftShift;
569 const WORD* srcpixel;
570 DWORD* dstpixel;
571 int x,y;
573 /* Note, the source pixel value is shifted left by 16 bits so that
574 * we know we will always have to shift right to extract the components.
576 rRightShift1=16+X11DRV_DIB_MaskToShift(rsrc)-3;
577 gRightShift1=16+X11DRV_DIB_MaskToShift(gsrc)-3;
578 bRightShift1=16+X11DRV_DIB_MaskToShift(bsrc)-3;
579 rRightShift2=rRightShift1+5;
580 gRightShift2=gRightShift1+5;
581 bRightShift2=bRightShift1+5;
582 if (gsrc==0x03e0) {
583 /* Green has 5 bits, like the others */
584 gMask1=0xf8;
585 gMask2=0x07;
586 } else {
587 /* Green has 6 bits, not 5. Compensate. */
588 gRightShift1++;
589 gRightShift2+=2;
590 gMask1=0xfc;
591 gMask2=0x03;
594 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
595 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
596 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
598 for (y=0; y<height; y++) {
599 srcpixel=srcbits;
600 dstpixel=dstbits;
601 for (x=0; x<width; x++) {
602 DWORD srcval;
603 BYTE red,green,blue;
604 srcval=*srcpixel++ << 16;
605 red= ((srcval >> rRightShift1) & 0xf8) |
606 ((srcval >> rRightShift2) & 0x07);
607 green=((srcval >> gRightShift1) & gMask1) |
608 ((srcval >> gRightShift2) & gMask2);
609 blue= ((srcval >> bRightShift1) & 0xf8) |
610 ((srcval >> bRightShift2) & 0x07);
611 *dstpixel++=(red << rLeftShift) |
612 (green << gLeftShift) |
613 (blue << bLeftShift);
615 srcbits += srclinebytes;
616 dstbits += dstlinebytes;
621 * 16 bits conversions
624 static void X11DRV_DIB_Convert_565_reverse(int width, int height,
625 const void* srcbits, int srclinebytes,
626 void* dstbits, int dstlinebytes)
628 const DWORD* srcpixel;
629 DWORD* dstpixel;
630 int x,y;
632 for (y=0; y<height; y++) {
633 srcpixel=srcbits;
634 dstpixel=dstbits;
635 for (x=0; x<width/2; x++) {
636 /* Do 2 pixels at a time */
637 DWORD srcval;
638 srcval=*srcpixel++;
639 *dstpixel++=((srcval << 11) & 0xf800f800) | /* h */
640 ( srcval & 0x07e007e0) | /* g */
641 ((srcval >> 11) & 0x001f001f); /* l */
643 if (width&1) {
644 /* And the the odd pixel */
645 WORD srcval;
646 srcval=*((WORD*)srcpixel);
647 *((WORD*)dstpixel)=((srcval << 11) & 0xf800) | /* h */
648 ( srcval & 0x07e0) | /* g */
649 ((srcval >> 11) & 0x001f); /* l */
651 srcbits += srclinebytes;
652 dstbits += dstlinebytes;
656 static void X11DRV_DIB_Convert_565_to_555_asis(int width, int height,
657 const void* srcbits, int srclinebytes,
658 void* dstbits, int dstlinebytes)
660 const DWORD* srcpixel;
661 DWORD* dstpixel;
662 int x,y;
664 for (y=0; y<height; y++) {
665 srcpixel=srcbits;
666 dstpixel=dstbits;
667 for (x=0; x<width/2; x++) {
668 /* Do 2 pixels at a time */
669 DWORD srcval;
670 srcval=*srcpixel++;
671 *dstpixel++=((srcval >> 1) & 0x7fe07fe0) | /* h, g */
672 ( srcval & 0x001f001f); /* l */
674 if (width&1) {
675 /* And the the odd pixel */
676 WORD srcval;
677 srcval=*((WORD*)srcpixel);
678 *((WORD*)dstpixel)=((srcval >> 1) & 0x7fe0) | /* h, g */
679 ( srcval & 0x001f); /* l */
681 srcbits += srclinebytes;
682 dstbits += dstlinebytes;
686 static void X11DRV_DIB_Convert_565_to_555_reverse(int width, int height,
687 const void* srcbits, int srclinebytes,
688 void* dstbits, int dstlinebytes)
690 const DWORD* srcpixel;
691 DWORD* dstpixel;
692 int x,y;
694 for (y=0; y<height; y++) {
695 srcpixel=srcbits;
696 dstpixel=dstbits;
697 for (x=0; x<width/2; x++) {
698 /* Do 2 pixels at a time */
699 DWORD srcval;
700 srcval=*srcpixel++;
701 *dstpixel++=((srcval >> 11) & 0x001f001f) | /* h */
702 ((srcval >> 1) & 0x03e003e0) | /* g */
703 ((srcval << 10) & 0x7c007c00); /* l */
705 if (width&1) {
706 /* And the the odd pixel */
707 WORD srcval;
708 srcval=*((WORD*)srcpixel);
709 *((WORD*)dstpixel)=((srcval >> 11) & 0x001f) | /* h */
710 ((srcval >> 1) & 0x03e0) | /* g */
711 ((srcval << 10) & 0x7c00); /* l */
713 srcbits += srclinebytes;
714 dstbits += dstlinebytes;
718 static void X11DRV_DIB_Convert_565_to_888_asis(int width, int height,
719 const void* srcbits, int srclinebytes,
720 void* dstbits, int dstlinebytes)
722 const WORD* srcpixel;
723 BYTE* dstpixel;
724 int x,y;
726 for (y=0; y<height; y++) {
727 srcpixel=srcbits;
728 dstpixel=dstbits;
729 for (x=0; x<width; x++) {
730 WORD srcval;
731 srcval=*srcpixel++;
732 dstpixel[0]=((srcval << 3) & 0xf8) | /* l */
733 ((srcval >> 2) & 0x07); /* l - 3 bits */
734 dstpixel[1]=((srcval >> 3) & 0xfc) | /* g */
735 ((srcval >> 9) & 0x03); /* g - 2 bits */
736 dstpixel[2]=((srcval >> 8) & 0xf8) | /* h */
737 ((srcval >> 13) & 0x07); /* h - 3 bits */
738 dstpixel+=3;
740 srcbits += srclinebytes;
741 dstbits += dstlinebytes;
745 static void X11DRV_DIB_Convert_565_to_888_reverse(int width, int height,
746 const void* srcbits, int srclinebytes,
747 void* dstbits, int dstlinebytes)
749 const WORD* srcpixel;
750 BYTE* dstpixel;
751 int x,y;
753 for (y=0; y<height; y++) {
754 srcpixel=srcbits;
755 dstpixel=dstbits;
756 for (x=0; x<width; x++) {
757 WORD srcval;
758 srcval=*srcpixel++;
759 dstpixel[0]=((srcval >> 8) & 0xf8) | /* h */
760 ((srcval >> 13) & 0x07); /* h - 3 bits */
761 dstpixel[1]=((srcval >> 3) & 0xfc) | /* g */
762 ((srcval >> 9) & 0x03); /* g - 2 bits */
763 dstpixel[2]=((srcval << 3) & 0xf8) | /* l */
764 ((srcval >> 2) & 0x07); /* l - 3 bits */
765 dstpixel+=3;
767 srcbits += srclinebytes;
768 dstbits += dstlinebytes;
772 static void X11DRV_DIB_Convert_565_to_0888_asis(int width, int height,
773 const void* srcbits, int srclinebytes,
774 void* dstbits, int dstlinebytes)
776 const WORD* srcpixel;
777 DWORD* dstpixel;
778 int x,y;
780 for (y=0; y<height; y++) {
781 srcpixel=srcbits;
782 dstpixel=dstbits;
783 for (x=0; x<width; x++) {
784 WORD srcval;
785 srcval=*srcpixel++;
786 *dstpixel++=((srcval << 8) & 0xf80000) | /* h */
787 ((srcval << 3) & 0x070000) | /* h - 3 bits */
788 ((srcval << 5) & 0x00fc00) | /* g */
789 ((srcval >> 1) & 0x000300) | /* g - 2 bits */
790 ((srcval << 3) & 0x0000f8) | /* l */
791 ((srcval >> 2) & 0x000007); /* l - 3 bits */
793 srcbits += srclinebytes;
794 dstbits += dstlinebytes;
798 static void X11DRV_DIB_Convert_565_to_0888_reverse(int width, int height,
799 const void* srcbits, int srclinebytes,
800 void* dstbits, int dstlinebytes)
802 const WORD* srcpixel;
803 DWORD* dstpixel;
804 int x,y;
806 for (y=0; y<height; y++) {
807 srcpixel=srcbits;
808 dstpixel=dstbits;
809 for (x=0; x<width; x++) {
810 WORD srcval;
811 srcval=*srcpixel++;
812 *dstpixel++=((srcval >> 8) & 0x0000f8) | /* h */
813 ((srcval >> 13) & 0x000007) | /* h - 3 bits */
814 ((srcval << 5) & 0x00fc00) | /* g */
815 ((srcval >> 1) & 0x000300) | /* g - 2 bits */
816 ((srcval << 19) & 0xf80000) | /* l */
817 ((srcval << 14) & 0x070000); /* l - 3 bits */
819 srcbits += srclinebytes;
820 dstbits += dstlinebytes;
825 * 24 bit conversions
828 static void X11DRV_DIB_Convert_888_reverse(int width, int height,
829 const void* srcbits, int srclinebytes,
830 void* dstbits, int dstlinebytes)
832 const BYTE* srcpixel;
833 BYTE* dstpixel;
834 int x,y;
836 for (y=0; y<height; y++) {
837 srcpixel=srcbits;
838 dstpixel=dstbits;
839 for (x=0; x<width; x++) {
840 dstpixel[0]=srcpixel[2];
841 dstpixel[1]=srcpixel[1];
842 dstpixel[2]=srcpixel[0];
843 srcpixel+=3;
844 dstpixel+=3;
846 srcbits += srclinebytes;
847 dstbits += dstlinebytes;
851 static void X11DRV_DIB_Convert_888_to_555_asis(int width, int height,
852 const void* srcbits, int srclinebytes,
853 void* dstbits, int dstlinebytes)
855 const DWORD* srcpixel;
856 const BYTE* srcbyte;
857 WORD* dstpixel;
858 int x,y;
859 int oddwidth;
861 oddwidth=width & 3;
862 width=width/4;
863 for (y=0; y<height; y++) {
864 srcpixel=srcbits;
865 dstpixel=dstbits;
866 for (x=0; x<width; x++) {
867 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
868 DWORD srcval1,srcval2;
869 srcval1=srcpixel[0];
870 dstpixel[0]=((srcval1 >> 3) & 0x001f) | /* l1 */
871 ((srcval1 >> 6) & 0x03e0) | /* g1 */
872 ((srcval1 >> 9) & 0x7c00); /* h1 */
873 srcval2=srcpixel[1];
874 dstpixel[1]=((srcval1 >> 27) & 0x001f) | /* l2 */
875 ((srcval2 << 2) & 0x03e0) | /* g2 */
876 ((srcval2 >> 1) & 0x7c00); /* h2 */
877 srcval1=srcpixel[2];
878 dstpixel[2]=((srcval2 >> 19) & 0x001f) | /* l3 */
879 ((srcval2 >> 22) & 0x03e0) | /* g3 */
880 ((srcval1 << 7) & 0x7c00); /* h3 */
881 dstpixel[3]=((srcval1 >> 11) & 0x001f) | /* l4 */
882 ((srcval1 >> 14) & 0x03e0) | /* g4 */
883 ((srcval1 >> 17) & 0x7c00); /* h4 */
884 srcpixel+=3;
885 dstpixel+=4;
887 /* And now up to 3 odd pixels */
888 srcbyte=(LPBYTE)srcpixel;
889 for (x=0; x<oddwidth; x++) {
890 WORD dstval;
891 dstval =((srcbyte[0] >> 3) & 0x001f); /* l */
892 dstval|=((srcbyte[1] << 2) & 0x03e0); /* g */
893 dstval|=((srcbyte[2] << 7) & 0x7c00); /* h */
894 *dstpixel++=dstval;
895 srcbyte+=3;
897 srcbits += srclinebytes;
898 dstbits += dstlinebytes;
902 static void X11DRV_DIB_Convert_888_to_555_reverse(int width, int height,
903 const void* srcbits, int srclinebytes,
904 void* dstbits, int dstlinebytes)
906 const DWORD* srcpixel;
907 const BYTE* srcbyte;
908 WORD* dstpixel;
909 int x,y;
910 int oddwidth;
912 oddwidth=width & 3;
913 width=width/4;
914 for (y=0; y<height; y++) {
915 srcpixel=srcbits;
916 dstpixel=dstbits;
917 for (x=0; x<width; x++) {
918 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
919 DWORD srcval1,srcval2;
920 srcval1=srcpixel[0];
921 dstpixel[0]=((srcval1 << 7) & 0x7c00) | /* l1 */
922 ((srcval1 >> 6) & 0x03e0) | /* g1 */
923 ((srcval1 >> 19) & 0x001f); /* h1 */
924 srcval2=srcpixel[1];
925 dstpixel[1]=((srcval1 >> 17) & 0x7c00) | /* l2 */
926 ((srcval2 << 2) & 0x03e0) | /* g2 */
927 ((srcval2 >> 11) & 0x001f); /* h2 */
928 srcval1=srcpixel[2];
929 dstpixel[2]=((srcval2 >> 9) & 0x7c00) | /* l3 */
930 ((srcval2 >> 22) & 0x03e0) | /* g3 */
931 ((srcval1 >> 3) & 0x001f); /* h3 */
932 dstpixel[3]=((srcval1 >> 1) & 0x7c00) | /* l4 */
933 ((srcval1 >> 14) & 0x03e0) | /* g4 */
934 ((srcval1 >> 27) & 0x001f); /* h4 */
935 srcpixel+=3;
936 dstpixel+=4;
938 /* And now up to 3 odd pixels */
939 srcbyte=(LPBYTE)srcpixel;
940 for (x=0; x<oddwidth; x++) {
941 WORD dstval;
942 dstval =((srcbyte[0] << 7) & 0x7c00); /* l */
943 dstval|=((srcbyte[1] << 2) & 0x03e0); /* g */
944 dstval|=((srcbyte[2] >> 3) & 0x001f); /* h */
945 *dstpixel++=dstval;
946 srcbyte+=3;
948 srcbits += srclinebytes;
949 dstbits += dstlinebytes;
953 static void X11DRV_DIB_Convert_888_to_565_asis(int width, int height,
954 const void* srcbits, int srclinebytes,
955 void* dstbits, int dstlinebytes)
957 const DWORD* srcpixel;
958 const BYTE* srcbyte;
959 WORD* dstpixel;
960 int x,y;
961 int oddwidth;
963 oddwidth=width & 3;
964 width=width/4;
965 for (y=0; y<height; y++) {
966 srcpixel=srcbits;
967 dstpixel=dstbits;
968 for (x=0; x<width; x++) {
969 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
970 DWORD srcval1,srcval2;
971 srcval1=srcpixel[0];
972 dstpixel[0]=((srcval1 >> 3) & 0x001f) | /* l1 */
973 ((srcval1 >> 5) & 0x07e0) | /* g1 */
974 ((srcval1 >> 8) & 0xf800); /* h1 */
975 srcval2=srcpixel[1];
976 dstpixel[1]=((srcval1 >> 27) & 0x001f) | /* l2 */
977 ((srcval2 << 3) & 0x07e0) | /* g2 */
978 ( srcval2 & 0xf800); /* h2 */
979 srcval1=srcpixel[2];
980 dstpixel[2]=((srcval2 >> 19) & 0x001f) | /* l3 */
981 ((srcval2 >> 21) & 0x07e0) | /* g3 */
982 ((srcval1 << 8) & 0xf800); /* h3 */
983 dstpixel[3]=((srcval1 >> 11) & 0x001f) | /* l4 */
984 ((srcval1 >> 13) & 0x07e0) | /* g4 */
985 ((srcval1 >> 16) & 0xf800); /* h4 */
986 srcpixel+=3;
987 dstpixel+=4;
989 /* And now up to 3 odd pixels */
990 srcbyte=(LPBYTE)srcpixel;
991 for (x=0; x<oddwidth; x++) {
992 WORD dstval;
993 dstval =((srcbyte[0] >> 3) & 0x001f); /* l */
994 dstval|=((srcbyte[1] << 3) & 0x07e0); /* g */
995 dstval|=((srcbyte[2] << 8) & 0xf800); /* h */
996 *dstpixel++=dstval;
997 srcbyte+=3;
999 srcbits += srclinebytes;
1000 dstbits += dstlinebytes;
1004 static void X11DRV_DIB_Convert_888_to_565_reverse(int width, int height,
1005 const void* srcbits, int srclinebytes,
1006 void* dstbits, int dstlinebytes)
1008 const DWORD* srcpixel;
1009 const BYTE* srcbyte;
1010 WORD* dstpixel;
1011 int x,y;
1012 int oddwidth;
1014 oddwidth=width & 3;
1015 width=width/4;
1016 for (y=0; y<height; y++) {
1017 srcpixel=srcbits;
1018 dstpixel=dstbits;
1019 for (x=0; x<width; x++) {
1020 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
1021 DWORD srcval1,srcval2;
1022 srcval1=srcpixel[0];
1023 dstpixel[0]=((srcval1 << 8) & 0xf800) | /* l1 */
1024 ((srcval1 >> 5) & 0x07e0) | /* g1 */
1025 ((srcval1 >> 19) & 0x001f); /* h1 */
1026 srcval2=srcpixel[1];
1027 dstpixel[1]=((srcval1 >> 16) & 0xf800) | /* l2 */
1028 ((srcval2 << 3) & 0x07e0) | /* g2 */
1029 ((srcval2 >> 11) & 0x001f); /* h2 */
1030 srcval1=srcpixel[2];
1031 dstpixel[2]=((srcval2 >> 8) & 0xf800) | /* l3 */
1032 ((srcval2 >> 21) & 0x07e0) | /* g3 */
1033 ((srcval1 >> 3) & 0x001f); /* h3 */
1034 dstpixel[3]=(srcval1 & 0xf800) | /* l4 */
1035 ((srcval1 >> 13) & 0x07e0) | /* g4 */
1036 ((srcval1 >> 27) & 0x001f); /* h4 */
1037 srcpixel+=3;
1038 dstpixel+=4;
1040 /* And now up to 3 odd pixels */
1041 srcbyte=(LPBYTE)srcpixel;
1042 for (x=0; x<oddwidth; x++) {
1043 WORD dstval;
1044 dstval =((srcbyte[0] << 8) & 0xf800); /* l */
1045 dstval|=((srcbyte[1] << 3) & 0x07e0); /* g */
1046 dstval|=((srcbyte[2] >> 3) & 0x001f); /* h */
1047 *dstpixel++=dstval;
1048 srcbyte+=3;
1050 srcbits += srclinebytes;
1051 dstbits += dstlinebytes;
1055 static void X11DRV_DIB_Convert_888_to_0888_asis(int width, int height,
1056 const void* srcbits, int srclinebytes,
1057 void* dstbits, int dstlinebytes)
1059 const DWORD* srcpixel;
1060 DWORD* dstpixel;
1061 int x,y;
1062 int oddwidth;
1064 oddwidth=width & 3;
1065 width=width/4;
1066 for (y=0; y<height; y++) {
1067 srcpixel=srcbits;
1068 dstpixel=dstbits;
1069 for (x=0; x<width; x++) {
1070 /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
1071 DWORD srcval1,srcval2;
1072 srcval1=srcpixel[0];
1073 dstpixel[0]=( srcval1 & 0x00ffffff); /* h1, g1, l1 */
1074 srcval2=srcpixel[1];
1075 dstpixel[1]=( srcval1 >> 24) | /* l2 */
1076 ((srcval2 << 8) & 0x00ffff00); /* h2, g2 */
1077 srcval1=srcpixel[2];
1078 dstpixel[2]=( srcval2 >> 16) | /* g3, l3 */
1079 ((srcval1 << 16) & 0x00ff0000); /* h3 */
1080 dstpixel[3]=( srcval1 >> 8); /* h4, g4, l4 */
1081 srcpixel+=3;
1082 dstpixel+=4;
1084 /* And now up to 3 odd pixels */
1085 for (x=0; x<oddwidth; x++) {
1086 DWORD srcval;
1087 srcval=*srcpixel;
1088 srcpixel=(LPDWORD)(((char*)srcpixel)+3);
1089 *dstpixel++=( srcval & 0x00ffffff); /* h, g, l */
1091 srcbits += srclinebytes;
1092 dstbits += dstlinebytes;
1096 static void X11DRV_DIB_Convert_888_to_0888_reverse(int width, int height,
1097 const void* srcbits, int srclinebytes,
1098 void* dstbits, int dstlinebytes)
1100 const DWORD* srcpixel;
1101 DWORD* dstpixel;
1102 int x,y;
1103 int oddwidth;
1105 oddwidth=width & 3;
1106 width=width/4;
1107 for (y=0; y<height; y++) {
1108 srcpixel=srcbits;
1109 dstpixel=dstbits;
1110 for (x=0; x<width; x++) {
1111 /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
1112 DWORD srcval1,srcval2;
1114 srcval1=srcpixel[0];
1115 dstpixel[0]=((srcval1 >> 16) & 0x0000ff) | /* h1 */
1116 ( srcval1 & 0x00ff00) | /* g1 */
1117 ((srcval1 << 16) & 0xff0000); /* l1 */
1118 srcval2=srcpixel[1];
1119 dstpixel[1]=((srcval1 >> 8) & 0xff0000) | /* l2 */
1120 ((srcval2 << 8) & 0x00ff00) | /* g2 */
1121 ((srcval2 >> 8) & 0x0000ff); /* h2 */
1122 srcval1=srcpixel[2];
1123 dstpixel[2]=( srcval2 & 0xff0000) | /* l3 */
1124 ((srcval2 >> 16) & 0x00ff00) | /* g3 */
1125 ( srcval1 & 0x0000ff); /* h3 */
1126 dstpixel[3]=((srcval1 >> 24) & 0x0000ff) | /* h4 */
1127 ((srcval1 >> 8) & 0x00ff00) | /* g4 */
1128 ((srcval1 << 8) & 0xff0000); /* l4 */
1129 srcpixel+=3;
1130 dstpixel+=4;
1132 /* And now up to 3 odd pixels */
1133 for (x=0; x<oddwidth; x++) {
1134 DWORD srcval;
1135 srcval=*srcpixel;
1136 srcpixel=(LPDWORD)(((char*)srcpixel)+3);
1137 *dstpixel++=((srcval >> 16) & 0x0000ff) | /* h */
1138 ( srcval & 0x00ff00) | /* g */
1139 ((srcval << 16) & 0xff0000); /* l */
1141 srcbits += srclinebytes;
1142 dstbits += dstlinebytes;
1146 static void X11DRV_DIB_Convert_rgb888_to_any0888(int width, int height,
1147 const void* srcbits, int srclinebytes,
1148 void* dstbits, int dstlinebytes,
1149 DWORD rdst, DWORD gdst, DWORD bdst)
1151 int rLeftShift,gLeftShift,bLeftShift;
1152 const BYTE* srcpixel;
1153 DWORD* dstpixel;
1154 int x,y;
1156 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1157 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1158 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1159 for (y=0; y<height; y++) {
1160 srcpixel=srcbits;
1161 dstpixel=dstbits;
1162 for (x=0; x<width; x++) {
1163 *dstpixel++=(srcpixel[0] << bLeftShift) | /* b */
1164 (srcpixel[1] << gLeftShift) | /* g */
1165 (srcpixel[2] << rLeftShift); /* r */
1166 srcpixel+=3;
1168 srcbits += srclinebytes;
1169 dstbits += dstlinebytes;
1173 static void X11DRV_DIB_Convert_bgr888_to_any0888(int width, int height,
1174 const void* srcbits, int srclinebytes,
1175 void* dstbits, int dstlinebytes,
1176 DWORD rdst, DWORD gdst, DWORD bdst)
1178 int rLeftShift,gLeftShift,bLeftShift;
1179 const BYTE* srcpixel;
1180 DWORD* dstpixel;
1181 int x,y;
1183 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1184 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1185 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1186 for (y=0; y<height; y++) {
1187 srcpixel=srcbits;
1188 dstpixel=dstbits;
1189 for (x=0; x<width; x++) {
1190 *dstpixel++=(srcpixel[0] << rLeftShift) | /* r */
1191 (srcpixel[1] << gLeftShift) | /* g */
1192 (srcpixel[2] << bLeftShift); /* b */
1193 srcpixel+=3;
1195 srcbits += srclinebytes;
1196 dstbits += dstlinebytes;
1201 * 32 bit conversions
1204 static void X11DRV_DIB_Convert_0888_reverse(int width, int height,
1205 const void* srcbits, int srclinebytes,
1206 void* dstbits, int dstlinebytes)
1208 const DWORD* srcpixel;
1209 DWORD* dstpixel;
1210 int x,y;
1212 for (y=0; y<height; y++) {
1213 srcpixel=srcbits;
1214 dstpixel=dstbits;
1215 for (x=0; x<width; x++) {
1216 DWORD srcval;
1217 srcval=*srcpixel++;
1218 *dstpixel++=((srcval << 16) & 0x00ff0000) | /* h */
1219 ( srcval & 0x0000ff00) | /* g */
1220 ((srcval >> 16) & 0x000000ff); /* l */
1222 srcbits += srclinebytes;
1223 dstbits += dstlinebytes;
1227 static void X11DRV_DIB_Convert_0888_any(int width, int height,
1228 const void* srcbits, int srclinebytes,
1229 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1230 void* dstbits, int dstlinebytes,
1231 DWORD rdst, DWORD gdst, DWORD bdst)
1233 int rRightShift,gRightShift,bRightShift;
1234 int rLeftShift,gLeftShift,bLeftShift;
1235 const DWORD* srcpixel;
1236 DWORD* dstpixel;
1237 int x,y;
1239 rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1240 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1241 bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1242 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1243 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1244 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1245 for (y=0; y<height; y++) {
1246 srcpixel=srcbits;
1247 dstpixel=dstbits;
1248 for (x=0; x<width; x++) {
1249 DWORD srcval;
1250 srcval=*srcpixel++;
1251 *dstpixel++=(((srcval >> rRightShift) & 0xff) << rLeftShift) |
1252 (((srcval >> gRightShift) & 0xff) << gLeftShift) |
1253 (((srcval >> bRightShift) & 0xff) << bLeftShift);
1255 srcbits += srclinebytes;
1256 dstbits += dstlinebytes;
1260 static void X11DRV_DIB_Convert_0888_to_555_asis(int width, int height,
1261 const void* srcbits, int srclinebytes,
1262 void* dstbits, int dstlinebytes)
1264 const DWORD* srcpixel;
1265 WORD* dstpixel;
1266 int x,y;
1268 for (y=0; y<height; y++) {
1269 srcpixel=srcbits;
1270 dstpixel=dstbits;
1271 for (x=0; x<width; x++) {
1272 DWORD srcval;
1273 srcval=*srcpixel++;
1274 *dstpixel++=((srcval >> 9) & 0x7c00) | /* h */
1275 ((srcval >> 6) & 0x03e0) | /* g */
1276 ((srcval >> 3) & 0x001f); /* l */
1278 srcbits += srclinebytes;
1279 dstbits += dstlinebytes;
1283 static void X11DRV_DIB_Convert_0888_to_555_reverse(int width, int height,
1284 const void* srcbits, int srclinebytes,
1285 void* dstbits, int dstlinebytes)
1287 const DWORD* srcpixel;
1288 WORD* dstpixel;
1289 int x,y;
1291 for (y=0; y<height; y++) {
1292 srcpixel=srcbits;
1293 dstpixel=dstbits;
1294 for (x=0; x<width; x++) {
1295 DWORD srcval;
1296 srcval=*srcpixel++;
1297 *dstpixel++=((srcval >> 19) & 0x001f) | /* h */
1298 ((srcval >> 6) & 0x03e0) | /* g */
1299 ((srcval << 7) & 0x7c00); /* l */
1301 srcbits += srclinebytes;
1302 dstbits += dstlinebytes;
1306 static void X11DRV_DIB_Convert_0888_to_565_asis(int width, int height,
1307 const void* srcbits, int srclinebytes,
1308 void* dstbits, int dstlinebytes)
1310 const DWORD* srcpixel;
1311 WORD* dstpixel;
1312 int x,y;
1314 for (y=0; y<height; y++) {
1315 srcpixel=srcbits;
1316 dstpixel=dstbits;
1317 for (x=0; x<width; x++) {
1318 DWORD srcval;
1319 srcval=*srcpixel++;
1320 *dstpixel++=((srcval >> 8) & 0xf800) | /* h */
1321 ((srcval >> 5) & 0x07e0) | /* g */
1322 ((srcval >> 3) & 0x001f); /* l */
1324 srcbits += srclinebytes;
1325 dstbits += dstlinebytes;
1329 static void X11DRV_DIB_Convert_0888_to_565_reverse(int width, int height,
1330 const void* srcbits, int srclinebytes,
1331 void* dstbits, int dstlinebytes)
1333 const DWORD* srcpixel;
1334 WORD* dstpixel;
1335 int x,y;
1337 for (y=0; y<height; y++) {
1338 srcpixel=srcbits;
1339 dstpixel=dstbits;
1340 for (x=0; x<width; x++) {
1341 DWORD srcval;
1342 srcval=*srcpixel++;
1343 *dstpixel++=((srcval >> 19) & 0x001f) | /* h */
1344 ((srcval >> 5) & 0x07e0) | /* g */
1345 ((srcval << 8) & 0xf800); /* l */
1347 srcbits += srclinebytes;
1348 dstbits += dstlinebytes;
1352 static void X11DRV_DIB_Convert_any0888_to_5x5(int width, int height,
1353 const void* srcbits, int srclinebytes,
1354 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1355 void* dstbits, int dstlinebytes,
1356 WORD rdst, WORD gdst, WORD bdst)
1358 int rRightShift,gRightShift,bRightShift;
1359 int rLeftShift,gLeftShift,bLeftShift;
1360 const DWORD* srcpixel;
1361 WORD* dstpixel;
1362 int x,y;
1364 /* Here is how we proceed. Assume we have rsrc=0x0000ff00 and our pixel
1365 * contains 0x11223344.
1366 * - first we shift 0x11223344 right by rRightShift to bring the most
1367 * significant bits of the red components in the bottom 5 (or 6) bits
1368 * -> 0x4488c
1369 * - then we remove non red bits by anding with the modified rdst (0x1f)
1370 * -> 0x0c
1371 * - finally shift these bits left by rLeftShift so that they end up in
1372 * the right place
1373 * -> 0x3000
1375 rRightShift=X11DRV_DIB_MaskToShift(rsrc)+3;
1376 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1377 gRightShift+=(gdst==0x07e0?2:3);
1378 bRightShift=X11DRV_DIB_MaskToShift(bsrc)+3;
1380 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1381 rdst=rdst >> rLeftShift;
1382 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1383 gdst=gdst >> gLeftShift;
1384 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1385 bdst=bdst >> bLeftShift;
1387 for (y=0; y<height; y++) {
1388 srcpixel=srcbits;
1389 dstpixel=dstbits;
1390 for (x=0; x<width; x++) {
1391 DWORD srcval;
1392 srcval=*srcpixel++;
1393 *dstpixel++=(((srcval >> rRightShift) & rdst) << rLeftShift) |
1394 (((srcval >> gRightShift) & gdst) << gLeftShift) |
1395 (((srcval >> bRightShift) & bdst) << bLeftShift);
1397 srcbits += srclinebytes;
1398 dstbits += dstlinebytes;
1402 static void X11DRV_DIB_Convert_0888_to_888_asis(int width, int height,
1403 const void* srcbits, int srclinebytes,
1404 void* dstbits, int dstlinebytes)
1406 const DWORD* srcpixel;
1407 DWORD* dstpixel;
1408 BYTE* dstbyte;
1409 int x,y;
1410 int oddwidth;
1412 oddwidth=width & 3;
1413 width=width/4;
1414 for (y=0; y<height; y++) {
1415 srcpixel=srcbits;
1416 dstpixel=dstbits;
1417 for (x=0; x<width; x++) {
1418 /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */
1419 DWORD srcval;
1420 srcval=((*srcpixel++) & 0x00ffffff); /* h1, g1, l1*/
1421 *dstpixel++=srcval | ((*srcpixel) << 24); /* h2 */
1422 srcval=((*srcpixel++ >> 8 ) & 0x0000ffff); /* g2, l2 */
1423 *dstpixel++=srcval | ((*srcpixel) << 16); /* h3, g3 */
1424 srcval=((*srcpixel++ >> 16) & 0x000000ff); /* l3 */
1425 *dstpixel++=srcval | ((*srcpixel++) << 8); /* h4, g4, l4 */
1427 /* And now up to 3 odd pixels */
1428 dstbyte=(BYTE*)dstpixel;
1429 for (x=0; x<oddwidth; x++) {
1430 DWORD srcval;
1431 srcval=*srcpixel++;
1432 *((WORD*)dstbyte)++=srcval; /* h, g */
1433 *dstbyte++=srcval >> 16; /* l */
1435 srcbits += srclinebytes;
1436 dstbits += dstlinebytes;
1440 static void X11DRV_DIB_Convert_0888_to_888_reverse(int width, int height,
1441 const void* srcbits, int srclinebytes,
1442 void* dstbits, int dstlinebytes)
1444 const DWORD* srcpixel;
1445 DWORD* dstpixel;
1446 BYTE* dstbyte;
1447 int x,y;
1448 int oddwidth;
1450 oddwidth=width & 3;
1451 width=width/4;
1452 for (y=0; y<height; y++) {
1453 srcpixel=srcbits;
1454 dstpixel=dstbits;
1455 for (x=0; x<width; x++) {
1456 /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */
1457 DWORD srcval1,srcval2;
1458 srcval1=*srcpixel++;
1459 srcval2= ((srcval1 >> 16) & 0x000000ff) | /* h1 */
1460 ( srcval1 & 0x0000ff00) | /* g1 */
1461 ((srcval1 << 16) & 0x00ff0000); /* l1 */
1462 srcval1=*srcpixel++;
1463 *dstpixel++=srcval2 |
1464 ((srcval1 << 8) & 0xff000000); /* h2 */
1465 srcval2= ((srcval1 >> 8) & 0x000000ff) | /* g2 */
1466 ((srcval1 << 8) & 0x0000ff00); /* l2 */
1467 srcval1=*srcpixel++;
1468 *dstpixel++=srcval2 |
1469 ( srcval1 & 0x00ff0000) | /* h3 */
1470 ((srcval1 << 16) & 0xff000000); /* g3 */
1471 srcval2= ( srcval1 & 0x000000ff); /* l3 */
1472 srcval1=*srcpixel++;
1473 *dstpixel++=srcval2 |
1474 ((srcval1 >> 8) & 0x0000ff00) | /* h4 */
1475 ((srcval1 << 8) & 0x00ff0000) | /* g4 */
1476 ( srcval1 << 24); /* l4 */
1478 /* And now up to 3 odd pixels */
1479 dstbyte=(BYTE*)dstpixel;
1480 for (x=0; x<oddwidth; x++) {
1481 DWORD srcval;
1482 srcval=*srcpixel++;
1483 *((WORD*)dstbyte)++=((srcval >> 16) & 0x00ff) | /* h */
1484 (srcval & 0xff00); /* g */
1485 *dstbyte++=srcval; /* l */
1487 srcbits += srclinebytes;
1488 dstbits += dstlinebytes;
1492 static void X11DRV_DIB_Convert_any0888_to_rgb888(int width, int height,
1493 const void* srcbits, int srclinebytes,
1494 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1495 void* dstbits, int dstlinebytes)
1497 int rRightShift,gRightShift,bRightShift;
1498 const DWORD* srcpixel;
1499 BYTE* dstpixel;
1500 int x,y;
1502 rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1503 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1504 bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1505 for (y=0; y<height; y++) {
1506 srcpixel=srcbits;
1507 dstpixel=dstbits;
1508 for (x=0; x<width; x++) {
1509 DWORD srcval;
1510 srcval=*srcpixel++;
1511 dstpixel[0]=(srcval >> bRightShift); /* b */
1512 dstpixel[1]=(srcval >> gRightShift); /* g */
1513 dstpixel[2]=(srcval >> rRightShift); /* r */
1514 dstpixel+=3;
1516 srcbits += srclinebytes;
1517 dstbits += dstlinebytes;
1521 static void X11DRV_DIB_Convert_any0888_to_bgr888(int width, int height,
1522 const void* srcbits, int srclinebytes,
1523 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1524 void* dstbits, int dstlinebytes)
1526 int rRightShift,gRightShift,bRightShift;
1527 const DWORD* srcpixel;
1528 BYTE* dstpixel;
1529 int x,y;
1531 rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1532 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1533 bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1534 for (y=0; y<height; y++) {
1535 srcpixel=srcbits;
1536 dstpixel=dstbits;
1537 for (x=0; x<width; x++) {
1538 DWORD srcval;
1539 srcval=*srcpixel++;
1540 dstpixel[0]=(srcval >> rRightShift); /* r */
1541 dstpixel[1]=(srcval >> gRightShift); /* g */
1542 dstpixel[2]=(srcval >> bRightShift); /* b */
1543 dstpixel+=3;
1545 srcbits += srclinebytes;
1546 dstbits += dstlinebytes;
1550 /***********************************************************************
1551 * X11DRV_DIB_SetImageBits_1
1553 * SetDIBits for a 1-bit deep DIB.
1555 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
1556 DWORD srcwidth, DWORD dstwidth, int left,
1557 int *colors, XImage *bmpImage, DWORD linebytes)
1559 int h;
1560 const BYTE* srcbyte;
1561 BYTE srcval, extra;
1562 DWORD i, x;
1564 if (lines < 0 ) {
1565 lines = -lines;
1566 srcbits = srcbits + linebytes * (lines - 1);
1567 linebytes = -linebytes;
1570 if ((extra = (left & 7)) != 0) {
1571 left &= ~7;
1572 dstwidth += extra;
1574 srcbits += left >> 3;
1576 /* ==== pal 1 dib -> any bmp format ==== */
1577 for (h = lines-1; h >=0; h--) {
1578 srcbyte=srcbits;
1579 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
1580 for (i = dstwidth/8, x = left; i > 0; i--) {
1581 srcval=*srcbyte++;
1582 XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
1583 XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
1584 XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
1585 XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
1586 XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
1587 XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
1588 XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
1589 XPutPixel( bmpImage, x++, h, colors[ srcval & 1] );
1591 srcval=*srcbyte;
1592 switch (dstwidth & 7)
1594 case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1595 case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1596 case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1597 case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1598 case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1599 case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1600 case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
1602 srcbits += linebytes;
1606 /***********************************************************************
1607 * X11DRV_DIB_GetImageBits_1
1609 * GetDIBits for a 1-bit deep DIB.
1611 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
1612 DWORD dstwidth, DWORD srcwidth,
1613 RGBQUAD *colors, PALETTEENTRY *srccolors,
1614 XImage *bmpImage, DWORD linebytes )
1616 DWORD x;
1617 int h;
1619 if (lines < 0 ) {
1620 lines = -lines;
1621 dstbits = dstbits + linebytes * (lines - 1);
1622 linebytes = -linebytes;
1625 switch (bmpImage->depth)
1627 case 1:
1628 case 4:
1629 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1630 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
1631 BYTE* dstbyte;
1633 for (h=lines-1; h>=0; h--) {
1634 BYTE dstval;
1635 dstbyte=dstbits;
1636 dstval=0;
1637 for (x=0; x<dstwidth; x++) {
1638 PALETTEENTRY srcval;
1639 srcval=srccolors[XGetPixel(bmpImage, x, h)];
1640 dstval|=(X11DRV_DIB_GetNearestIndex
1641 (colors, 2,
1642 srcval.peRed,
1643 srcval.peGreen,
1644 srcval.peBlue) << (7 - (x & 7)));
1645 if ((x&7)==7) {
1646 *dstbyte++=dstval;
1647 dstval=0;
1650 if ((dstwidth&7)!=0) {
1651 *dstbyte=dstval;
1653 dstbits += linebytes;
1655 } else {
1656 goto notsupported;
1658 break;
1660 case 8:
1661 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1662 /* ==== pal 8 bmp -> pal 1 dib ==== */
1663 const void* srcbits;
1664 const BYTE* srcpixel;
1665 BYTE* dstbyte;
1667 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1669 for (h=0; h<lines; h++) {
1670 BYTE dstval;
1671 srcpixel=srcbits;
1672 dstbyte=dstbits;
1673 dstval=0;
1674 for (x=0; x<dstwidth; x++) {
1675 PALETTEENTRY srcval;
1676 srcval=srccolors[(int)*srcpixel++];
1677 dstval|=(X11DRV_DIB_GetNearestIndex
1678 (colors, 2,
1679 srcval.peRed,
1680 srcval.peGreen,
1681 srcval.peBlue) << (7-(x&7)) );
1682 if ((x&7)==7) {
1683 *dstbyte++=dstval;
1684 dstval=0;
1687 if ((dstwidth&7)!=0) {
1688 *dstbyte=dstval;
1690 srcbits -= bmpImage->bytes_per_line;
1691 dstbits += linebytes;
1693 } else {
1694 goto notsupported;
1696 break;
1698 case 15:
1699 case 16:
1701 const void* srcbits;
1702 const WORD* srcpixel;
1703 BYTE* dstbyte;
1705 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1707 if (bmpImage->green_mask==0x03e0) {
1708 if (bmpImage->red_mask==0x7c00) {
1709 /* ==== rgb 555 bmp -> pal 1 dib ==== */
1710 for (h=0; h<lines; h++) {
1711 BYTE dstval;
1712 srcpixel=srcbits;
1713 dstbyte=dstbits;
1714 dstval=0;
1715 for (x=0; x<dstwidth; x++) {
1716 WORD srcval;
1717 srcval=*srcpixel++;
1718 dstval|=(X11DRV_DIB_GetNearestIndex
1719 (colors, 2,
1720 ((srcval >> 7) & 0xf8) | /* r */
1721 ((srcval >> 12) & 0x07),
1722 ((srcval >> 2) & 0xf8) | /* g */
1723 ((srcval >> 7) & 0x07),
1724 ((srcval << 3) & 0xf8) | /* b */
1725 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
1726 if ((x&7)==7) {
1727 *dstbyte++=dstval;
1728 dstval=0;
1731 if ((dstwidth&7)!=0) {
1732 *dstbyte=dstval;
1734 srcbits -= bmpImage->bytes_per_line;
1735 dstbits += linebytes;
1737 } else if (bmpImage->blue_mask==0x7c00) {
1738 /* ==== bgr 555 bmp -> pal 1 dib ==== */
1739 for (h=0; h<lines; h++) {
1740 WORD dstval;
1741 srcpixel=srcbits;
1742 dstbyte=dstbits;
1743 dstval=0;
1744 for (x=0; x<dstwidth; x++) {
1745 BYTE srcval;
1746 srcval=*srcpixel++;
1747 dstval|=(X11DRV_DIB_GetNearestIndex
1748 (colors, 2,
1749 ((srcval << 3) & 0xf8) | /* r */
1750 ((srcval >> 2) & 0x07),
1751 ((srcval >> 2) & 0xf8) | /* g */
1752 ((srcval >> 7) & 0x07),
1753 ((srcval >> 7) & 0xf8) | /* b */
1754 ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
1755 if ((x&7)==7) {
1756 *dstbyte++=dstval;
1757 dstval=0;
1760 if ((dstwidth&7)!=0) {
1761 *dstbyte=dstval;
1763 srcbits -= bmpImage->bytes_per_line;
1764 dstbits += linebytes;
1766 } else {
1767 goto notsupported;
1769 } else if (bmpImage->green_mask==0x07e0) {
1770 if (bmpImage->red_mask==0xf800) {
1771 /* ==== rgb 565 bmp -> pal 1 dib ==== */
1772 for (h=0; h<lines; h++) {
1773 BYTE dstval;
1774 srcpixel=srcbits;
1775 dstbyte=dstbits;
1776 dstval=0;
1777 for (x=0; x<dstwidth; x++) {
1778 WORD srcval;
1779 srcval=*srcpixel++;
1780 dstval|=(X11DRV_DIB_GetNearestIndex
1781 (colors, 2,
1782 ((srcval >> 8) & 0xf8) | /* r */
1783 ((srcval >> 13) & 0x07),
1784 ((srcval >> 3) & 0xfc) | /* g */
1785 ((srcval >> 9) & 0x03),
1786 ((srcval << 3) & 0xf8) | /* b */
1787 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
1788 if ((x&7)==7) {
1789 *dstbyte++=dstval;
1790 dstval=0;
1793 if ((dstwidth&7)!=0) {
1794 *dstbyte=dstval;
1796 srcbits -= bmpImage->bytes_per_line;
1797 dstbits += linebytes;
1799 } else if (bmpImage->blue_mask==0xf800) {
1800 /* ==== bgr 565 bmp -> pal 1 dib ==== */
1801 for (h=0; h<lines; h++) {
1802 BYTE dstval;
1803 srcpixel=srcbits;
1804 dstbyte=dstbits;
1805 dstval=0;
1806 for (x=0; x<dstwidth; x++) {
1807 WORD srcval;
1808 srcval=*srcpixel++;
1809 dstval|=(X11DRV_DIB_GetNearestIndex
1810 (colors, 2,
1811 ((srcval << 3) & 0xf8) | /* r */
1812 ((srcval >> 2) & 0x07),
1813 ((srcval >> 3) & 0xfc) | /* g */
1814 ((srcval >> 9) & 0x03),
1815 ((srcval >> 8) & 0xf8) | /* b */
1816 ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
1817 if ((x&7)==7) {
1818 *dstbyte++=dstval;
1819 dstval=0;
1822 if ((dstwidth&7)!=0) {
1823 *dstbyte=dstval;
1825 srcbits -= bmpImage->bytes_per_line;
1826 dstbits += linebytes;
1828 } else {
1829 goto notsupported;
1831 } else {
1832 goto notsupported;
1835 break;
1837 case 24:
1838 case 32:
1840 const void* srcbits;
1841 const BYTE *srcbyte;
1842 BYTE* dstbyte;
1843 int bytes_per_pixel;
1845 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1846 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1848 if (bmpImage->green_mask!=0x00ff00 ||
1849 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1850 goto notsupported;
1851 } else if (bmpImage->blue_mask==0xff) {
1852 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
1853 for (h=0; h<lines; h++) {
1854 BYTE dstval;
1855 srcbyte=srcbits;
1856 dstbyte=dstbits;
1857 dstval=0;
1858 for (x=0; x<dstwidth; x++) {
1859 dstval|=(X11DRV_DIB_GetNearestIndex
1860 (colors, 2,
1861 srcbyte[2],
1862 srcbyte[1],
1863 srcbyte[0]) << (7-(x&7)) );
1864 srcbyte+=bytes_per_pixel;
1865 if ((x&7)==7) {
1866 *dstbyte++=dstval;
1867 dstval=0;
1870 if ((dstwidth&7)!=0) {
1871 *dstbyte=dstval;
1873 srcbits -= bmpImage->bytes_per_line;
1874 dstbits += linebytes;
1876 } else {
1877 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
1878 for (h=0; h<lines; h++) {
1879 BYTE dstval;
1880 srcbyte=srcbits;
1881 dstbyte=dstbits;
1882 dstval=0;
1883 for (x=0; x<dstwidth; x++) {
1884 dstval|=(X11DRV_DIB_GetNearestIndex
1885 (colors, 2,
1886 srcbyte[0],
1887 srcbyte[1],
1888 srcbyte[2]) << (7-(x&7)) );
1889 srcbyte+=bytes_per_pixel;
1890 if ((x&7)==7) {
1891 *dstbyte++=dstval;
1892 dstval=0;
1895 if ((dstwidth&7)!=0) {
1896 *dstbyte=dstval;
1898 srcbits -= bmpImage->bytes_per_line;
1899 dstbits += linebytes;
1903 break;
1905 default:
1906 notsupported:
1908 BYTE* dstbyte;
1909 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
1911 /* ==== any bmp format -> pal 1 dib ==== */
1912 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
1913 bmpImage->bits_per_pixel, bmpImage->red_mask,
1914 bmpImage->green_mask, bmpImage->blue_mask );
1916 for (h=lines-1; h>=0; h--) {
1917 BYTE dstval;
1918 dstbyte=dstbits;
1919 dstval=0;
1920 for (x=0; x<dstwidth; x++) {
1921 dstval|=(XGetPixel( bmpImage, x, h) >= white) << (7 - (x&7));
1922 if ((x&7)==7) {
1923 *dstbyte++=dstval;
1924 dstval=0;
1927 if ((dstwidth&7)!=0) {
1928 *dstbyte=dstval;
1930 dstbits += linebytes;
1933 break;
1937 /***********************************************************************
1938 * X11DRV_DIB_SetImageBits_4
1940 * SetDIBits for a 4-bit deep DIB.
1942 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
1943 DWORD srcwidth, DWORD dstwidth, int left,
1944 int *colors, XImage *bmpImage, DWORD linebytes)
1946 int h;
1947 const BYTE* srcbyte;
1948 DWORD i, x;
1950 if (lines < 0 ) {
1951 lines = -lines;
1952 srcbits = srcbits + linebytes * (lines - 1);
1953 linebytes = -linebytes;
1956 if (left & 1) {
1957 left--;
1958 dstwidth++;
1960 srcbits += left >> 1;
1962 /* ==== pal 4 dib -> any bmp format ==== */
1963 for (h = lines-1; h >= 0; h--) {
1964 srcbyte=srcbits;
1965 for (i = dstwidth/2, x = left; i > 0; i--) {
1966 BYTE srcval=*srcbyte++;
1967 XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
1968 XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
1970 if (dstwidth & 1)
1971 XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
1972 srcbits += linebytes;
1978 /***********************************************************************
1979 * X11DRV_DIB_GetImageBits_4
1981 * GetDIBits for a 4-bit deep DIB.
1983 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
1984 DWORD srcwidth, DWORD dstwidth,
1985 RGBQUAD *colors, PALETTEENTRY *srccolors,
1986 XImage *bmpImage, DWORD linebytes )
1988 DWORD x;
1989 int h;
1990 BYTE *bits;
1992 if (lines < 0 )
1994 lines = -lines;
1995 dstbits = dstbits + ( linebytes * (lines-1) );
1996 linebytes = -linebytes;
1999 bits = dstbits;
2001 switch (bmpImage->depth) {
2002 case 1:
2003 case 4:
2004 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2005 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
2006 BYTE* dstbyte;
2008 for (h = lines-1; h >= 0; h--) {
2009 BYTE dstval;
2010 dstbyte=dstbits;
2011 dstval=0;
2012 for (x = 0; x < dstwidth; x++) {
2013 PALETTEENTRY srcval;
2014 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2015 dstval|=(X11DRV_DIB_GetNearestIndex
2016 (colors, 16,
2017 srcval.peRed,
2018 srcval.peGreen,
2019 srcval.peBlue) << (4-((x&1)<<2)));
2020 if ((x&1)==1) {
2021 *dstbyte++=dstval;
2022 dstval=0;
2025 if ((dstwidth&1)!=0) {
2026 *dstbyte=dstval;
2028 dstbits += linebytes;
2030 } else {
2031 goto notsupported;
2033 break;
2035 case 8:
2036 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2037 /* ==== pal 8 bmp -> pal 4 dib ==== */
2038 const void* srcbits;
2039 const BYTE *srcpixel;
2040 BYTE* dstbyte;
2042 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2043 for (h=0; h<lines; h++) {
2044 BYTE dstval;
2045 srcpixel=srcbits;
2046 dstbyte=dstbits;
2047 dstval=0;
2048 for (x=0; x<dstwidth; x++) {
2049 PALETTEENTRY srcval;
2050 srcval = srccolors[(int)*srcpixel++];
2051 dstval|=(X11DRV_DIB_GetNearestIndex
2052 (colors, 16,
2053 srcval.peRed,
2054 srcval.peGreen,
2055 srcval.peBlue) << (4*(1-(x&1))) );
2056 if ((x&1)==1) {
2057 *dstbyte++=dstval;
2058 dstval=0;
2061 if ((dstwidth&1)!=0) {
2062 *dstbyte=dstval;
2064 srcbits -= bmpImage->bytes_per_line;
2065 dstbits += linebytes;
2067 } else {
2068 goto notsupported;
2070 break;
2072 case 15:
2073 case 16:
2075 const void* srcbits;
2076 const WORD* srcpixel;
2077 BYTE* dstbyte;
2079 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2081 if (bmpImage->green_mask==0x03e0) {
2082 if (bmpImage->red_mask==0x7c00) {
2083 /* ==== rgb 555 bmp -> pal 4 dib ==== */
2084 for (h=0; h<lines; h++) {
2085 BYTE dstval;
2086 srcpixel=srcbits;
2087 dstbyte=dstbits;
2088 dstval=0;
2089 for (x=0; x<dstwidth; x++) {
2090 WORD srcval;
2091 srcval=*srcpixel++;
2092 dstval|=(X11DRV_DIB_GetNearestIndex
2093 (colors, 16,
2094 ((srcval >> 7) & 0xf8) | /* r */
2095 ((srcval >> 12) & 0x07),
2096 ((srcval >> 2) & 0xf8) | /* g */
2097 ((srcval >> 7) & 0x07),
2098 ((srcval << 3) & 0xf8) | /* b */
2099 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
2100 if ((x&1)==1) {
2101 *dstbyte++=dstval;
2102 dstval=0;
2105 if ((dstwidth&1)!=0) {
2106 *dstbyte=dstval;
2108 srcbits -= bmpImage->bytes_per_line;
2109 dstbits += linebytes;
2111 } else if (bmpImage->blue_mask==0x7c00) {
2112 /* ==== bgr 555 bmp -> pal 4 dib ==== */
2113 for (h=0; h<lines; h++) {
2114 WORD dstval;
2115 srcpixel=srcbits;
2116 dstbyte=dstbits;
2117 dstval=0;
2118 for (x=0; x<dstwidth; x++) {
2119 WORD srcval;
2120 srcval=*srcpixel++;
2121 dstval|=(X11DRV_DIB_GetNearestIndex
2122 (colors, 16,
2123 ((srcval << 3) & 0xf8) | /* r */
2124 ((srcval >> 2) & 0x07),
2125 ((srcval >> 2) & 0xf8) | /* g */
2126 ((srcval >> 7) & 0x07),
2127 ((srcval >> 7) & 0xf8) | /* b */
2128 ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
2129 if ((x&1)==1) {
2130 *dstbyte++=dstval;
2131 dstval=0;
2134 if ((dstwidth&1)!=0) {
2135 *dstbyte=dstval;
2137 srcbits -= bmpImage->bytes_per_line;
2138 dstbits += linebytes;
2140 } else {
2141 goto notsupported;
2143 } else if (bmpImage->green_mask==0x07e0) {
2144 if (bmpImage->red_mask==0xf800) {
2145 /* ==== rgb 565 bmp -> pal 4 dib ==== */
2146 for (h=0; h<lines; h++) {
2147 BYTE dstval;
2148 srcpixel=srcbits;
2149 dstbyte=dstbits;
2150 dstval=0;
2151 for (x=0; x<dstwidth; x++) {
2152 WORD srcval;
2153 srcval=*srcpixel++;
2154 dstval|=(X11DRV_DIB_GetNearestIndex
2155 (colors, 16,
2156 ((srcval >> 8) & 0xf8) | /* r */
2157 ((srcval >> 13) & 0x07),
2158 ((srcval >> 3) & 0xfc) | /* g */
2159 ((srcval >> 9) & 0x03),
2160 ((srcval << 3) & 0xf8) | /* b */
2161 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
2162 if ((x&1)==1) {
2163 *dstbyte++=dstval;
2164 dstval=0;
2167 if ((dstwidth&1)!=0) {
2168 *dstbyte=dstval;
2170 srcbits -= bmpImage->bytes_per_line;
2171 dstbits += linebytes;
2173 } else if (bmpImage->blue_mask==0xf800) {
2174 /* ==== bgr 565 bmp -> pal 4 dib ==== */
2175 for (h=0; h<lines; h++) {
2176 WORD dstval;
2177 srcpixel=srcbits;
2178 dstbyte=dstbits;
2179 dstval=0;
2180 for (x=0; x<dstwidth; x++) {
2181 WORD srcval;
2182 srcval=*srcpixel++;
2183 dstval|=(X11DRV_DIB_GetNearestIndex
2184 (colors, 16,
2185 ((srcval << 3) & 0xf8) | /* r */
2186 ((srcval >> 2) & 0x07),
2187 ((srcval >> 3) & 0xfc) | /* g */
2188 ((srcval >> 9) & 0x03),
2189 ((srcval >> 8) & 0xf8) | /* b */
2190 ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
2191 if ((x&1)==1) {
2192 *dstbyte++=dstval;
2193 dstval=0;
2196 if ((dstwidth&1)!=0) {
2197 *dstbyte=dstval;
2199 srcbits -= bmpImage->bytes_per_line;
2200 dstbits += linebytes;
2202 } else {
2203 goto notsupported;
2205 } else {
2206 goto notsupported;
2209 break;
2211 case 24:
2212 if (bmpImage->bits_per_pixel==24) {
2213 const void* srcbits;
2214 const BYTE *srcbyte;
2215 BYTE* dstbyte;
2217 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2219 if (bmpImage->green_mask!=0x00ff00 ||
2220 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2221 goto notsupported;
2222 } else if (bmpImage->blue_mask==0xff) {
2223 /* ==== rgb 888 bmp -> pal 4 dib ==== */
2224 for (h=0; h<lines; h++) {
2225 srcbyte=srcbits;
2226 dstbyte=dstbits;
2227 for (x=0; x<dstwidth/2; x++) {
2228 /* Do 2 pixels at a time */
2229 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2230 (colors, 16,
2231 srcbyte[2],
2232 srcbyte[1],
2233 srcbyte[0]) << 4) |
2234 X11DRV_DIB_GetNearestIndex
2235 (colors, 16,
2236 srcbyte[5],
2237 srcbyte[4],
2238 srcbyte[3]);
2239 srcbyte+=6;
2241 if (dstwidth&1) {
2242 /* And the the odd pixel */
2243 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2244 (colors, 16,
2245 srcbyte[2],
2246 srcbyte[1],
2247 srcbyte[0]) << 4);
2249 srcbits -= bmpImage->bytes_per_line;
2250 dstbits += linebytes;
2252 } else {
2253 /* ==== bgr 888 bmp -> pal 4 dib ==== */
2254 for (h=0; h<lines; h++) {
2255 srcbyte=srcbits;
2256 dstbyte=dstbits;
2257 for (x=0; x<dstwidth/2; x++) {
2258 /* Do 2 pixels at a time */
2259 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2260 (colors, 16,
2261 srcbyte[0],
2262 srcbyte[1],
2263 srcbyte[2]) << 4) |
2264 X11DRV_DIB_GetNearestIndex
2265 (colors, 16,
2266 srcbyte[3],
2267 srcbyte[4],
2268 srcbyte[5]);
2269 srcbyte+=6;
2271 if (dstwidth&1) {
2272 /* And the the odd pixel */
2273 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2274 (colors, 16,
2275 srcbyte[0],
2276 srcbyte[1],
2277 srcbyte[2]) << 4);
2279 srcbits -= bmpImage->bytes_per_line;
2280 dstbits += linebytes;
2283 break;
2285 /* Fall through */
2287 case 32:
2289 const void* srcbits;
2290 const BYTE *srcbyte;
2291 BYTE* dstbyte;
2293 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2295 if (bmpImage->green_mask!=0x00ff00 ||
2296 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2297 goto notsupported;
2298 } else if (bmpImage->blue_mask==0xff) {
2299 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
2300 for (h=0; h<lines; h++) {
2301 srcbyte=srcbits;
2302 dstbyte=dstbits;
2303 for (x=0; x<dstwidth/2; x++) {
2304 /* Do 2 pixels at a time */
2305 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2306 (colors, 16,
2307 srcbyte[2],
2308 srcbyte[1],
2309 srcbyte[0]) << 4) |
2310 X11DRV_DIB_GetNearestIndex
2311 (colors, 16,
2312 srcbyte[6],
2313 srcbyte[5],
2314 srcbyte[4]);
2315 srcbyte+=8;
2317 if (dstwidth&1) {
2318 /* And the the odd pixel */
2319 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2320 (colors, 16,
2321 srcbyte[2],
2322 srcbyte[1],
2323 srcbyte[0]) << 4);
2325 srcbits -= bmpImage->bytes_per_line;
2326 dstbits += linebytes;
2328 } else {
2329 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
2330 for (h=0; h<lines; h++) {
2331 srcbyte=srcbits;
2332 dstbyte=dstbits;
2333 for (x=0; x<dstwidth/2; x++) {
2334 /* Do 2 pixels at a time */
2335 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2336 (colors, 16,
2337 srcbyte[0],
2338 srcbyte[1],
2339 srcbyte[2]) << 4) |
2340 X11DRV_DIB_GetNearestIndex
2341 (colors, 16,
2342 srcbyte[4],
2343 srcbyte[5],
2344 srcbyte[6]);
2345 srcbyte+=8;
2347 if (dstwidth&1) {
2348 /* And the the odd pixel */
2349 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2350 (colors, 16,
2351 srcbyte[0],
2352 srcbyte[1],
2353 srcbyte[2]) << 4);
2355 srcbits -= bmpImage->bytes_per_line;
2356 dstbits += linebytes;
2360 break;
2362 default:
2363 notsupported:
2365 BYTE* dstbyte;
2367 /* ==== any bmp format -> pal 4 dib ==== */
2368 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
2369 bmpImage->bits_per_pixel, bmpImage->red_mask,
2370 bmpImage->green_mask, bmpImage->blue_mask );
2371 for (h=lines-1; h>=0; h--) {
2372 dstbyte=dstbits;
2373 for (x=0; x<(dstwidth & ~1); x+=2) {
2374 *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
2375 X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
2377 if (dstwidth & 1) {
2378 *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
2380 dstbits += linebytes;
2383 break;
2387 /***********************************************************************
2388 * X11DRV_DIB_SetImageBits_RLE4
2390 * SetDIBits for a 4-bit deep compressed DIB.
2392 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
2393 DWORD width, DWORD dstwidth,
2394 int left, int *colors,
2395 XImage *bmpImage )
2397 int x = 0, y = lines - 1, c, length;
2398 const BYTE *begin = bits;
2400 while (y >= 0)
2402 length = *bits++;
2403 if (length) { /* encoded */
2404 c = *bits++;
2405 while (length--) {
2406 if (x >= width) break;
2407 XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2408 if (!length--) break;
2409 if (x >= width) break;
2410 XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2412 } else {
2413 length = *bits++;
2414 switch (length)
2416 case RLE_EOL:
2417 x = 0;
2418 y--;
2419 break;
2421 case RLE_END:
2422 return;
2424 case RLE_DELTA:
2425 x += *bits++;
2426 y -= *bits++;
2427 break;
2429 default: /* absolute */
2430 while (length--) {
2431 c = *bits++;
2432 if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2433 if (!length--) break;
2434 if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2436 if ((bits - begin) & 1)
2437 bits++;
2445 /***********************************************************************
2446 * X11DRV_DIB_SetImageBits_8
2448 * SetDIBits for an 8-bit deep DIB.
2450 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
2451 DWORD srcwidth, DWORD dstwidth, int left,
2452 const int *colors, XImage *bmpImage,
2453 DWORD linebytes )
2455 DWORD x;
2456 int h;
2457 const BYTE* srcbyte;
2458 BYTE* dstbits;
2460 if (lines < 0 )
2462 lines = -lines;
2463 srcbits = srcbits + linebytes * (lines-1);
2464 linebytes = -linebytes;
2466 srcbits += left;
2467 srcbyte = srcbits;
2469 switch (bmpImage->depth) {
2470 case 15:
2471 case 16:
2472 #if defined(__i386__) && defined(__GNUC__)
2473 /* Some X servers might have 32 bit/ 16bit deep pixel */
2474 if (lines && dstwidth && (bmpImage->bits_per_pixel == 16))
2476 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2477 /* FIXME: Does this really handle all these cases correctly? */
2478 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
2479 for (h = lines ; h--; ) {
2480 int _cl1,_cl2; /* temp outputs for asm below */
2481 /* Borrowed from DirectDraw */
2482 __asm__ __volatile__(
2483 "xor %%eax,%%eax\n"
2484 "cld\n"
2485 "1:\n"
2486 " lodsb\n"
2487 " movw (%%edx,%%eax,4),%%ax\n"
2488 " stosw\n"
2489 " xor %%eax,%%eax\n"
2490 " loop 1b\n"
2491 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2492 :"S" (srcbyte),
2493 "D" (dstbits),
2494 "c" (dstwidth),
2495 "d" (colors)
2496 :"eax", "cc", "memory"
2498 srcbyte = (srcbits += linebytes);
2499 dstbits -= bmpImage->bytes_per_line;
2501 return;
2503 break;
2504 #endif
2505 case 24:
2506 case 32:
2507 #if defined(__i386__) && defined(__GNUC__)
2508 if (lines && dstwidth && (bmpImage->bits_per_pixel == 32))
2510 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2511 /* FIXME: Does this really handle both cases correctly? */
2512 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
2513 for (h = lines ; h--; ) {
2514 int _cl1,_cl2; /* temp outputs for asm below */
2515 /* Borrowed from DirectDraw */
2516 __asm__ __volatile__(
2517 "xor %%eax,%%eax\n"
2518 "cld\n"
2519 "1:\n"
2520 " lodsb\n"
2521 " movl (%%edx,%%eax,4),%%eax\n"
2522 " stosl\n"
2523 " xor %%eax,%%eax\n"
2524 " loop 1b\n"
2525 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2526 :"S" (srcbyte),
2527 "D" (dstbits),
2528 "c" (dstwidth),
2529 "d" (colors)
2530 :"eax", "cc", "memory"
2532 srcbyte = (srcbits += linebytes);
2533 dstbits -= bmpImage->bytes_per_line;
2535 return;
2537 break;
2538 #endif
2539 default:
2540 break; /* use slow generic case below */
2543 /* ==== pal 8 dib -> any bmp format ==== */
2544 for (h=lines-1; h>=0; h--) {
2545 for (x=left; x<dstwidth+left; x++) {
2546 XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
2548 srcbyte = (srcbits += linebytes);
2552 /***********************************************************************
2553 * X11DRV_DIB_GetImageBits_8
2555 * GetDIBits for an 8-bit deep DIB.
2557 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
2558 DWORD srcwidth, DWORD dstwidth,
2559 RGBQUAD *colors, PALETTEENTRY *srccolors,
2560 XImage *bmpImage, DWORD linebytes )
2562 DWORD x;
2563 int h;
2564 BYTE* dstbyte;
2566 if (lines < 0 )
2568 lines = -lines;
2569 dstbits = dstbits + ( linebytes * (lines-1) );
2570 linebytes = -linebytes;
2574 * Hack for now
2575 * This condition is true when GetImageBits has been called by
2576 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
2577 * 256 colormaps, so we'll just use for for GetDIBits calls.
2578 * (In somes cases, in a updateDIBSection, the returned colors are bad too)
2580 if (!srccolors) goto updatesection;
2582 switch (bmpImage->depth) {
2583 case 1:
2584 case 4:
2585 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2587 /* ==== pal 1 bmp -> pal 8 dib ==== */
2588 /* ==== pal 4 bmp -> pal 8 dib ==== */
2589 for (h=lines-1; h>=0; h--) {
2590 dstbyte=dstbits;
2591 for (x=0; x<dstwidth; x++) {
2592 PALETTEENTRY srcval;
2593 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2594 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2595 srcval.peRed,
2596 srcval.peGreen,
2597 srcval.peBlue);
2599 dstbits += linebytes;
2601 } else {
2602 goto notsupported;
2604 break;
2606 case 8:
2607 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2608 /* ==== pal 8 bmp -> pal 8 dib ==== */
2609 const void* srcbits;
2610 const BYTE* srcpixel;
2612 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2613 for (h=0; h<lines; h++) {
2614 srcpixel=srcbits;
2615 dstbyte=dstbits;
2616 for (x = 0; x < dstwidth; x++) {
2617 PALETTEENTRY srcval;
2618 srcval=srccolors[(int)*srcpixel++];
2619 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2620 srcval.peRed,
2621 srcval.peGreen,
2622 srcval.peBlue);
2624 srcbits -= bmpImage->bytes_per_line;
2625 dstbits += linebytes;
2627 } else {
2628 goto notsupported;
2630 break;
2632 case 15:
2633 case 16:
2635 const void* srcbits;
2636 const WORD* srcpixel;
2637 BYTE* dstbyte;
2639 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2641 if (bmpImage->green_mask==0x03e0) {
2642 if (bmpImage->red_mask==0x7c00) {
2643 /* ==== rgb 555 bmp -> pal 8 dib ==== */
2644 for (h=0; h<lines; h++) {
2645 srcpixel=srcbits;
2646 dstbyte=dstbits;
2647 for (x=0; x<dstwidth; x++) {
2648 WORD srcval;
2649 srcval=*srcpixel++;
2650 *dstbyte++=X11DRV_DIB_GetNearestIndex
2651 (colors, 256,
2652 ((srcval >> 7) & 0xf8) | /* r */
2653 ((srcval >> 12) & 0x07),
2654 ((srcval >> 2) & 0xf8) | /* g */
2655 ((srcval >> 7) & 0x07),
2656 ((srcval << 3) & 0xf8) | /* b */
2657 ((srcval >> 2) & 0x07) );
2659 srcbits -= bmpImage->bytes_per_line;
2660 dstbits += linebytes;
2662 } else if (bmpImage->blue_mask==0x7c00) {
2663 /* ==== bgr 555 bmp -> pal 8 dib ==== */
2664 for (h=0; h<lines; h++) {
2665 srcpixel=srcbits;
2666 dstbyte=dstbits;
2667 for (x=0; x<dstwidth; x++) {
2668 WORD srcval;
2669 srcval=*srcpixel++;
2670 *dstbyte++=X11DRV_DIB_GetNearestIndex
2671 (colors, 256,
2672 ((srcval << 3) & 0xf8) | /* r */
2673 ((srcval >> 2) & 0x07),
2674 ((srcval >> 2) & 0xf8) | /* g */
2675 ((srcval >> 7) & 0x07),
2676 ((srcval >> 7) & 0xf8) | /* b */
2677 ((srcval >> 12) & 0x07) );
2679 srcbits -= bmpImage->bytes_per_line;
2680 dstbits += linebytes;
2682 } else {
2683 goto notsupported;
2685 } else if (bmpImage->green_mask==0x07e0) {
2686 if (bmpImage->red_mask==0xf800) {
2687 /* ==== rgb 565 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 >> 8) & 0xf8) | /* r */
2697 ((srcval >> 13) & 0x07),
2698 ((srcval >> 3) & 0xfc) | /* g */
2699 ((srcval >> 9) & 0x03),
2700 ((srcval << 3) & 0xf8) | /* b */
2701 ((srcval >> 2) & 0x07) );
2703 srcbits -= bmpImage->bytes_per_line;
2704 dstbits += linebytes;
2706 } else if (bmpImage->blue_mask==0xf800) {
2707 /* ==== bgr 565 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 >> 3) & 0xfc) | /* g */
2719 ((srcval >> 9) & 0x03),
2720 ((srcval >> 8) & 0xf8) | /* b */
2721 ((srcval >> 13) & 0x07) );
2723 srcbits -= bmpImage->bytes_per_line;
2724 dstbits += linebytes;
2726 } else {
2727 goto notsupported;
2729 } else {
2730 goto notsupported;
2733 break;
2735 case 24:
2736 case 32:
2738 const void* srcbits;
2739 const BYTE *srcbyte;
2740 BYTE* dstbyte;
2741 int bytes_per_pixel;
2743 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2744 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
2746 if (bmpImage->green_mask!=0x00ff00 ||
2747 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2748 goto notsupported;
2749 } else if (bmpImage->blue_mask==0xff) {
2750 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
2751 for (h=0; h<lines; h++) {
2752 srcbyte=srcbits;
2753 dstbyte=dstbits;
2754 for (x=0; x<dstwidth; x++) {
2755 *dstbyte++=X11DRV_DIB_GetNearestIndex
2756 (colors, 256,
2757 srcbyte[2],
2758 srcbyte[1],
2759 srcbyte[0]);
2760 srcbyte+=bytes_per_pixel;
2762 srcbits -= bmpImage->bytes_per_line;
2763 dstbits += linebytes;
2765 } else {
2766 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
2767 for (h=0; h<lines; h++) {
2768 srcbyte=srcbits;
2769 dstbyte=dstbits;
2770 for (x=0; x<dstwidth; x++) {
2771 *dstbyte++=X11DRV_DIB_GetNearestIndex
2772 (colors, 256,
2773 srcbyte[0],
2774 srcbyte[1],
2775 srcbyte[2]);
2776 srcbyte+=bytes_per_pixel;
2778 srcbits -= bmpImage->bytes_per_line;
2779 dstbits += linebytes;
2783 break;
2785 default:
2786 notsupported:
2787 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
2788 bmpImage->depth, bmpImage->red_mask,
2789 bmpImage->green_mask, bmpImage->blue_mask );
2790 updatesection:
2791 /* ==== any bmp format -> pal 8 dib ==== */
2792 for (h=lines-1; h>=0; h--) {
2793 dstbyte=dstbits;
2794 for (x=0; x<dstwidth; x++) {
2795 *dstbyte=X11DRV_DIB_MapColor
2796 ((int*)colors, 256,
2797 XGetPixel(bmpImage, x, h), *dstbyte);
2798 dstbyte++;
2800 dstbits += linebytes;
2802 break;
2806 /***********************************************************************
2807 * X11DRV_DIB_SetImageBits_RLE8
2809 * SetDIBits for an 8-bit deep compressed DIB.
2811 * This function rewritten 941113 by James Youngman. WINE blew out when I
2812 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
2814 * This was because the algorithm assumed that all RLE8 bitmaps end with the
2815 * 'End of bitmap' escape code. This code is very much laxer in what it
2816 * allows to end the expansion. Possibly too lax. See the note by
2817 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
2818 * bitmap should end with RleEnd, but on the other hand, software exists
2819 * that produces ones that don't and Windows 3.1 doesn't complain a bit
2820 * about it.
2822 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
2823 * James A. Youngman <mbcstjy@afs.man.ac.uk>
2824 * [JAY]
2826 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
2827 DWORD width, DWORD dstwidth,
2828 int left, int *colors,
2829 XImage *bmpImage )
2831 int x; /* X-positon on each line. Increases. */
2832 int y; /* Line #. Starts at lines-1, decreases */
2833 const BYTE *pIn = bits; /* Pointer to current position in bits */
2834 BYTE length; /* The length pf a run */
2835 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
2838 * Note that the bitmap data is stored by Windows starting at the
2839 * bottom line of the bitmap and going upwards. Within each line,
2840 * the data is stored left-to-right. That's the reason why line
2841 * goes from lines-1 to 0. [JAY]
2844 x = 0;
2845 y = lines - 1;
2846 while (y >= 0)
2848 length = *pIn++;
2851 * If the length byte is not zero (which is the escape value),
2852 * We have a run of length pixels all the same colour. The colour
2853 * index is stored next.
2855 * If the length byte is zero, we need to read the next byte to
2856 * know what to do. [JAY]
2858 if (length != 0)
2861 * [Run-Length] Encoded mode
2863 int color = colors[*pIn++];
2864 while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
2866 else
2869 * Escape codes (may be an absolute sequence though)
2871 escape_code = (*pIn++);
2872 switch(escape_code)
2874 case RLE_EOL:
2875 x = 0;
2876 y--;
2877 break;
2879 case RLE_END:
2880 /* Not all RLE8 bitmaps end with this code. For
2881 * example, Paint Shop Pro produces some that don't.
2882 * That's (I think) what caused the previous
2883 * implementation to fail. [JAY]
2885 return;
2887 case RLE_DELTA:
2888 x += (*pIn++);
2889 y -= (*pIn++);
2890 break;
2892 default: /* switch to absolute mode */
2893 length = escape_code;
2894 while (length--)
2896 int color = colors[*pIn++];
2897 if (x >= dstwidth)
2899 pIn += length;
2900 break;
2902 XPutPixel(bmpImage, x++, y, color);
2905 * If you think for a moment you'll realise that the
2906 * only time we could ever possibly read an odd
2907 * number of bytes is when there is a 0x00 (escape),
2908 * a value >0x02 (absolute mode) and then an odd-
2909 * length run. Therefore this is the only place we
2910 * need to worry about it. Everywhere else the
2911 * bytes are always read in pairs. [JAY]
2913 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
2914 break;
2915 } /* switch (escape_code) : Escape sequence */
2921 /***********************************************************************
2922 * X11DRV_DIB_SetImageBits_16
2924 * SetDIBits for a 16-bit deep DIB.
2926 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
2927 DWORD srcwidth, DWORD dstwidth, int left,
2928 DC *dc, DWORD rSrc, DWORD gSrc, DWORD bSrc,
2929 XImage *bmpImage, DWORD linebytes )
2931 DWORD x;
2932 int h;
2934 if (lines < 0 )
2936 lines = -lines;
2937 srcbits = srcbits + ( linebytes * (lines-1));
2938 linebytes = -linebytes;
2941 switch (bmpImage->depth)
2943 case 15:
2944 case 16:
2946 char* dstbits;
2948 srcbits=srcbits+left*2;
2949 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2951 if (bmpImage->green_mask==0x03e0) {
2952 if (gSrc==bmpImage->green_mask) {
2953 if (rSrc==bmpImage->red_mask) {
2954 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
2955 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
2956 X11DRV_DIB_Convert_any_asis
2957 (dstwidth,lines,2,
2958 srcbits,linebytes,
2959 dstbits,-bmpImage->bytes_per_line);
2960 } else if (rSrc==bmpImage->blue_mask) {
2961 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
2962 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
2963 X11DRV_DIB_Convert_555_reverse
2964 (dstwidth,lines,
2965 srcbits,linebytes,
2966 dstbits,-bmpImage->bytes_per_line);
2968 } else {
2969 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
2970 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
2971 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
2972 X11DRV_DIB_Convert_565_to_555_asis
2973 (dstwidth,lines,
2974 srcbits,linebytes,
2975 dstbits,-bmpImage->bytes_per_line);
2976 } else {
2977 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
2978 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
2979 X11DRV_DIB_Convert_565_to_555_reverse
2980 (dstwidth,lines,
2981 srcbits,linebytes,
2982 dstbits,-bmpImage->bytes_per_line);
2985 } else if (bmpImage->green_mask==0x07e0) {
2986 if (gSrc==bmpImage->green_mask) {
2987 if (rSrc==bmpImage->red_mask) {
2988 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
2989 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
2990 X11DRV_DIB_Convert_any_asis
2991 (dstwidth,lines,2,
2992 srcbits,linebytes,
2993 dstbits,-bmpImage->bytes_per_line);
2994 } else {
2995 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
2996 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
2997 X11DRV_DIB_Convert_565_reverse
2998 (dstwidth,lines,
2999 srcbits,linebytes,
3000 dstbits,-bmpImage->bytes_per_line);
3002 } else {
3003 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
3004 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
3005 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
3006 X11DRV_DIB_Convert_555_to_565_asis
3007 (dstwidth,lines,
3008 srcbits,linebytes,
3009 dstbits,-bmpImage->bytes_per_line);
3010 } else {
3011 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
3012 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
3013 X11DRV_DIB_Convert_555_to_565_reverse
3014 (dstwidth,lines,
3015 srcbits,linebytes,
3016 dstbits,-bmpImage->bytes_per_line);
3019 } else {
3020 goto notsupported;
3023 break;
3025 case 24:
3026 if (bmpImage->bits_per_pixel==24) {
3027 char* dstbits;
3029 srcbits=srcbits+left*2;
3030 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3032 if (bmpImage->green_mask!=0x00ff00 ||
3033 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3034 goto notsupported;
3035 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3036 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3037 if (gSrc==0x03e0) {
3038 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
3039 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
3040 X11DRV_DIB_Convert_555_to_888_asis
3041 (dstwidth,lines,
3042 srcbits,linebytes,
3043 dstbits,-bmpImage->bytes_per_line);
3044 } else {
3045 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
3046 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
3047 X11DRV_DIB_Convert_565_to_888_asis
3048 (dstwidth,lines,
3049 srcbits,linebytes,
3050 dstbits,-bmpImage->bytes_per_line);
3052 } else {
3053 if (gSrc==0x03e0) {
3054 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
3055 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
3056 X11DRV_DIB_Convert_555_to_888_reverse
3057 (dstwidth,lines,
3058 srcbits,linebytes,
3059 dstbits,-bmpImage->bytes_per_line);
3060 } else {
3061 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
3062 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
3063 X11DRV_DIB_Convert_565_to_888_reverse
3064 (dstwidth,lines,
3065 srcbits,linebytes,
3066 dstbits,-bmpImage->bytes_per_line);
3069 break;
3071 /* Fall through */
3073 case 32:
3075 char* dstbits;
3077 srcbits=srcbits+left*2;
3078 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3080 if (bmpImage->green_mask!=0x00ff00 ||
3081 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3082 goto notsupported;
3083 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3084 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3085 if (gSrc==0x03e0) {
3086 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
3087 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
3088 X11DRV_DIB_Convert_555_to_0888_asis
3089 (dstwidth,lines,
3090 srcbits,linebytes,
3091 dstbits,-bmpImage->bytes_per_line);
3092 } else {
3093 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
3094 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
3095 X11DRV_DIB_Convert_565_to_0888_asis
3096 (dstwidth,lines,
3097 srcbits,linebytes,
3098 dstbits,-bmpImage->bytes_per_line);
3100 } else {
3101 if (gSrc==0x03e0) {
3102 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
3103 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
3104 X11DRV_DIB_Convert_555_to_0888_reverse
3105 (dstwidth,lines,
3106 srcbits,linebytes,
3107 dstbits,-bmpImage->bytes_per_line);
3108 } else {
3109 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
3110 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
3111 X11DRV_DIB_Convert_565_to_0888_reverse
3112 (dstwidth,lines,
3113 srcbits,linebytes,
3114 dstbits,-bmpImage->bytes_per_line);
3118 break;
3120 default:
3121 notsupported:
3122 WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3123 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3124 bmpImage->green_mask, bmpImage->blue_mask );
3125 /* fall through */
3126 case 1:
3127 case 4:
3128 case 8:
3130 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
3131 const WORD* srcpixel;
3132 int rShift1,gShift1,bShift1;
3133 int rShift2,gShift2,bShift2;
3134 BYTE gMask1,gMask2;
3136 /* Set color scaling values */
3137 rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
3138 gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
3139 bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
3140 rShift2=rShift1+5;
3141 gShift2=gShift1+5;
3142 bShift2=bShift1+5;
3143 if (gSrc==0x03e0) {
3144 /* Green has 5 bits, like the others */
3145 gMask1=0xf8;
3146 gMask2=0x07;
3147 } else {
3148 /* Green has 6 bits, not 5. Compensate. */
3149 gShift1++;
3150 gShift2+=2;
3151 gMask1=0xfc;
3152 gMask2=0x03;
3155 srcbits+=2*left;
3157 /* We could split it into four separate cases to optimize
3158 * but it is probably not worth it.
3160 for (h=lines-1; h>=0; h--) {
3161 srcpixel=(const WORD*)srcbits;
3162 for (x=left; x<dstwidth+left; x++) {
3163 DWORD srcval;
3164 BYTE red,green,blue;
3165 srcval=*srcpixel++ << 16;
3166 red= ((srcval >> rShift1) & 0xf8) |
3167 ((srcval >> rShift2) & 0x07);
3168 green=((srcval >> gShift1) & gMask1) |
3169 ((srcval >> gShift2) & gMask2);
3170 blue= ((srcval >> bShift1) & 0xf8) |
3171 ((srcval >> bShift2) & 0x07);
3172 XPutPixel(bmpImage, x, h,
3173 X11DRV_PALETTE_ToPhysical
3174 (dc, RGB(red,green,blue)));
3176 srcbits += linebytes;
3179 break;
3184 /***********************************************************************
3185 * X11DRV_DIB_GetImageBits_16
3187 * GetDIBits for an 16-bit deep DIB.
3189 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
3190 DWORD dstwidth, DWORD srcwidth,
3191 PALETTEENTRY *srccolors,
3192 DWORD rDst, DWORD gDst, DWORD bDst,
3193 XImage *bmpImage, DWORD dibpitch )
3195 DWORD x;
3196 int h;
3198 DWORD linebytes = dibpitch;
3200 if (lines < 0 )
3202 lines = -lines;
3203 dstbits = dstbits + ( linebytes * (lines-1));
3204 linebytes = -linebytes;
3207 switch (bmpImage->depth)
3209 case 15:
3210 case 16:
3212 const char* srcbits;
3214 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3216 if (bmpImage->green_mask==0x03e0) {
3217 if (gDst==bmpImage->green_mask) {
3218 if (rDst==bmpImage->red_mask) {
3219 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
3220 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
3221 X11DRV_DIB_Convert_any_asis
3222 (dstwidth,lines,2,
3223 srcbits,-bmpImage->bytes_per_line,
3224 dstbits,linebytes);
3225 } else {
3226 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
3227 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
3228 X11DRV_DIB_Convert_555_reverse
3229 (dstwidth,lines,
3230 srcbits,-bmpImage->bytes_per_line,
3231 dstbits,linebytes);
3233 } else {
3234 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3235 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
3236 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
3237 X11DRV_DIB_Convert_555_to_565_asis
3238 (dstwidth,lines,
3239 srcbits,-bmpImage->bytes_per_line,
3240 dstbits,linebytes);
3241 } else {
3242 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
3243 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
3244 X11DRV_DIB_Convert_555_to_565_reverse
3245 (dstwidth,lines,
3246 srcbits,-bmpImage->bytes_per_line,
3247 dstbits,linebytes);
3250 } else if (bmpImage->green_mask==0x07e0) {
3251 if (gDst==bmpImage->green_mask) {
3252 if (rDst == bmpImage->red_mask) {
3253 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
3254 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
3255 X11DRV_DIB_Convert_any_asis
3256 (dstwidth,lines,2,
3257 srcbits,-bmpImage->bytes_per_line,
3258 dstbits,linebytes);
3259 } else {
3260 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
3261 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
3262 X11DRV_DIB_Convert_565_reverse
3263 (dstwidth,lines,
3264 srcbits,-bmpImage->bytes_per_line,
3265 dstbits,linebytes);
3267 } else {
3268 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3269 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
3270 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
3271 X11DRV_DIB_Convert_565_to_555_asis
3272 (dstwidth,lines,
3273 srcbits,-bmpImage->bytes_per_line,
3274 dstbits,linebytes);
3275 } else {
3276 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
3277 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
3278 X11DRV_DIB_Convert_565_to_555_reverse
3279 (dstwidth,lines,
3280 srcbits,-bmpImage->bytes_per_line,
3281 dstbits,linebytes);
3284 } else {
3285 goto notsupported;
3288 break;
3290 case 24:
3291 if (bmpImage->bits_per_pixel == 24) {
3292 const char* srcbits;
3294 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3296 if (bmpImage->green_mask!=0x00ff00 ||
3297 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3298 goto notsupported;
3299 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3300 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3301 if (gDst==0x03e0) {
3302 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
3303 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
3304 X11DRV_DIB_Convert_888_to_555_asis
3305 (dstwidth,lines,
3306 srcbits,-bmpImage->bytes_per_line,
3307 dstbits,linebytes);
3308 } else {
3309 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3310 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3311 X11DRV_DIB_Convert_888_to_565_asis
3312 (dstwidth,lines,
3313 srcbits,-bmpImage->bytes_per_line,
3314 dstbits,linebytes);
3316 } else {
3317 if (gDst==0x03e0) {
3318 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
3319 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
3320 X11DRV_DIB_Convert_888_to_555_reverse
3321 (dstwidth,lines,
3322 srcbits,-bmpImage->bytes_per_line,
3323 dstbits,linebytes);
3324 } else {
3325 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
3326 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
3327 X11DRV_DIB_Convert_888_to_565_reverse
3328 (dstwidth,lines,
3329 srcbits,-bmpImage->bytes_per_line,
3330 dstbits,linebytes);
3333 break;
3335 /* Fall through */
3337 case 32:
3339 const char* srcbits;
3341 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3343 if (bmpImage->green_mask!=0x00ff00 ||
3344 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3345 goto notsupported;
3346 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3347 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3348 if (gDst==0x03e0) {
3349 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
3350 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
3351 X11DRV_DIB_Convert_0888_to_555_asis
3352 (dstwidth,lines,
3353 srcbits,-bmpImage->bytes_per_line,
3354 dstbits,linebytes);
3355 } else {
3356 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
3357 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
3358 X11DRV_DIB_Convert_0888_to_565_asis
3359 (dstwidth,lines,
3360 srcbits,-bmpImage->bytes_per_line,
3361 dstbits,linebytes);
3363 } else {
3364 if (gDst==0x03e0) {
3365 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
3366 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
3367 X11DRV_DIB_Convert_0888_to_555_reverse
3368 (dstwidth,lines,
3369 srcbits,-bmpImage->bytes_per_line,
3370 dstbits,linebytes);
3371 } else {
3372 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
3373 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
3374 X11DRV_DIB_Convert_0888_to_565_reverse
3375 (dstwidth,lines,
3376 srcbits,-bmpImage->bytes_per_line,
3377 dstbits,linebytes);
3381 break;
3383 case 1:
3384 case 4:
3385 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3386 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
3387 int rShift,gShift,bShift;
3388 WORD* dstpixel;
3390 /* Shift everything 16 bits left so that all shifts are >0,
3391 * even for BGR DIBs. Then a single >> 16 will bring everything
3392 * back into place.
3394 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3395 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3396 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3397 if (gDst==0x07e0) {
3398 /* 6 bits for the green */
3399 gShift++;
3401 rDst=rDst << 16;
3402 gDst=gDst << 16;
3403 bDst=bDst << 16;
3404 for (h = lines - 1; h >= 0; h--) {
3405 dstpixel=(LPWORD)dstbits;
3406 for (x = 0; x < dstwidth; x++) {
3407 PALETTEENTRY srcval;
3408 DWORD dstval;
3409 srcval=srccolors[XGetPixel(bmpImage, x, h)];
3410 dstval=((srcval.peRed << rShift) & rDst) |
3411 ((srcval.peGreen << gShift) & gDst) |
3412 ((srcval.peBlue << bShift) & bDst);
3413 *dstpixel++=dstval >> 16;
3415 dstbits += linebytes;
3417 } else {
3418 goto notsupported;
3420 break;
3422 case 8:
3423 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3424 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
3425 int rShift,gShift,bShift;
3426 const BYTE* srcbits;
3427 const BYTE* srcpixel;
3428 WORD* dstpixel;
3430 /* Shift everything 16 bits left so that all shifts are >0,
3431 * even for BGR DIBs. Then a single >> 16 will bring everything
3432 * back into place.
3434 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3435 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3436 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3437 if (gDst==0x07e0) {
3438 /* 6 bits for the green */
3439 gShift++;
3441 rDst=rDst << 16;
3442 gDst=gDst << 16;
3443 bDst=bDst << 16;
3444 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3445 for (h=0; h<lines; h++) {
3446 srcpixel=srcbits;
3447 dstpixel=(LPWORD)dstbits;
3448 for (x = 0; x < dstwidth; x++) {
3449 PALETTEENTRY srcval;
3450 DWORD dstval;
3451 srcval=srccolors[(int)*srcpixel++];
3452 dstval=((srcval.peRed << rShift) & rDst) |
3453 ((srcval.peGreen << gShift) & gDst) |
3454 ((srcval.peBlue << bShift) & bDst);
3455 *dstpixel++=dstval >> 16;
3457 srcbits -= bmpImage->bytes_per_line;
3458 dstbits += linebytes;
3460 } else {
3461 goto notsupported;
3463 break;
3465 default:
3466 notsupported:
3468 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
3469 int rShift,gShift,bShift;
3470 WORD* dstpixel;
3472 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
3473 bmpImage->depth, bmpImage->red_mask,
3474 bmpImage->green_mask, bmpImage->blue_mask,
3475 rDst, gDst, bDst);
3477 /* Shift everything 16 bits left so that all shifts are >0,
3478 * even for BGR DIBs. Then a single >> 16 will bring everything
3479 * back into place.
3481 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3482 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3483 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3484 if (gDst==0x07e0) {
3485 /* 6 bits for the green */
3486 gShift++;
3488 rDst=rDst << 16;
3489 gDst=gDst << 16;
3490 bDst=bDst << 16;
3491 for (h = lines - 1; h >= 0; h--) {
3492 dstpixel=(LPWORD)dstbits;
3493 for (x = 0; x < dstwidth; x++) {
3494 COLORREF srcval;
3495 DWORD dstval;
3496 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3497 dstval=((GetRValue(srcval) << rShift) & rDst) |
3498 ((GetGValue(srcval) << gShift) & gDst) |
3499 ((GetBValue(srcval) << bShift) & bDst);
3500 *dstpixel++=dstval >> 16;
3502 dstbits += linebytes;
3505 break;
3510 /***********************************************************************
3511 * X11DRV_DIB_SetImageBits_24
3513 * SetDIBits for a 24-bit deep DIB.
3515 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
3516 DWORD srcwidth, DWORD dstwidth, int left,
3517 DC *dc,
3518 DWORD rSrc, DWORD gSrc, DWORD bSrc,
3519 XImage *bmpImage, DWORD linebytes )
3521 DWORD x;
3522 int h;
3524 if (lines < 0 )
3526 lines = -lines;
3527 srcbits = srcbits + linebytes * (lines - 1);
3528 linebytes = -linebytes;
3531 switch (bmpImage->depth)
3533 case 24:
3534 if (bmpImage->bits_per_pixel==24) {
3535 char* dstbits;
3537 srcbits=srcbits+left*3;
3538 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3540 if (bmpImage->green_mask!=0x00ff00 ||
3541 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3542 goto notsupported;
3543 } else if (rSrc==bmpImage->red_mask) {
3544 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
3545 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
3546 X11DRV_DIB_Convert_any_asis
3547 (dstwidth,lines,3,
3548 srcbits,linebytes,
3549 dstbits,-bmpImage->bytes_per_line);
3550 } else {
3551 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
3552 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
3553 X11DRV_DIB_Convert_888_reverse
3554 (dstwidth,lines,
3555 srcbits,linebytes,
3556 dstbits,-bmpImage->bytes_per_line);
3558 break;
3560 /* fall through */
3562 case 32:
3564 char* dstbits;
3566 srcbits=srcbits+left*3;
3567 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3569 if (bmpImage->green_mask!=0x00ff00 ||
3570 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3571 goto notsupported;
3572 } else if (rSrc==bmpImage->red_mask) {
3573 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
3574 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
3575 X11DRV_DIB_Convert_888_to_0888_asis
3576 (dstwidth,lines,
3577 srcbits,linebytes,
3578 dstbits,-bmpImage->bytes_per_line);
3579 } else {
3580 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
3581 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
3582 X11DRV_DIB_Convert_888_to_0888_reverse
3583 (dstwidth,lines,
3584 srcbits,linebytes,
3585 dstbits,-bmpImage->bytes_per_line);
3587 break;
3590 case 15:
3591 case 16:
3593 char* dstbits;
3595 srcbits=srcbits+left*3;
3596 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
3598 if (bmpImage->green_mask==0x03e0) {
3599 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
3600 (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3601 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
3602 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
3603 X11DRV_DIB_Convert_888_to_555_asis
3604 (dstwidth,lines,
3605 srcbits,linebytes,
3606 dstbits,-bmpImage->bytes_per_line);
3607 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
3608 (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
3609 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
3610 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
3611 X11DRV_DIB_Convert_888_to_555_reverse
3612 (dstwidth,lines,
3613 srcbits,linebytes,
3614 dstbits,-bmpImage->bytes_per_line);
3615 } else {
3616 goto notsupported;
3618 } else if (bmpImage->green_mask==0x07e0) {
3619 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
3620 (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
3621 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
3622 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
3623 X11DRV_DIB_Convert_888_to_565_asis
3624 (dstwidth,lines,
3625 srcbits,linebytes,
3626 dstbits,-bmpImage->bytes_per_line);
3627 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
3628 (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
3629 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
3630 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
3631 X11DRV_DIB_Convert_888_to_565_reverse
3632 (dstwidth,lines,
3633 srcbits,linebytes,
3634 dstbits,-bmpImage->bytes_per_line);
3635 } else {
3636 goto notsupported;
3638 } else {
3639 goto notsupported;
3642 break;
3644 default:
3645 notsupported:
3646 WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3647 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3648 bmpImage->green_mask, bmpImage->blue_mask );
3649 /* fall through */
3650 case 1:
3651 case 4:
3652 case 8:
3654 /* ==== rgb 888 dib -> any bmp bormat ==== */
3655 const BYTE* srcbyte;
3657 /* Windows only supports one 24bpp DIB format: RGB888 */
3658 srcbits+=left*3;
3659 for (h = lines - 1; h >= 0; h--) {
3660 srcbyte=(const BYTE*)srcbits;
3661 for (x = left; x < dstwidth+left; x++) {
3662 XPutPixel(bmpImage, x, h,
3663 X11DRV_PALETTE_ToPhysical
3664 (dc, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
3665 srcbyte+=3;
3667 srcbits += linebytes;
3670 break;
3675 /***********************************************************************
3676 * X11DRV_DIB_GetImageBits_24
3678 * GetDIBits for an 24-bit deep DIB.
3680 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
3681 DWORD dstwidth, DWORD srcwidth,
3682 PALETTEENTRY *srccolors,
3683 DWORD rDst, DWORD gDst, DWORD bDst,
3684 XImage *bmpImage, DWORD linebytes )
3686 DWORD x;
3687 int h;
3689 if (lines < 0 )
3691 lines = -lines;
3692 dstbits = dstbits + ( linebytes * (lines-1) );
3693 linebytes = -linebytes;
3696 switch (bmpImage->depth)
3698 case 24:
3699 if (bmpImage->bits_per_pixel==24) {
3700 const char* srcbits;
3702 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3704 if (bmpImage->green_mask!=0x00ff00 ||
3705 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3706 goto notsupported;
3707 } else if (rDst==bmpImage->red_mask) {
3708 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
3709 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
3710 X11DRV_DIB_Convert_any_asis
3711 (dstwidth,lines,3,
3712 srcbits,-bmpImage->bytes_per_line,
3713 dstbits,linebytes);
3714 } else {
3715 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
3716 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
3717 X11DRV_DIB_Convert_888_reverse
3718 (dstwidth,lines,
3719 srcbits,-bmpImage->bytes_per_line,
3720 dstbits,linebytes);
3722 break;
3724 /* fall through */
3726 case 32:
3728 const char* srcbits;
3730 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3732 if (bmpImage->green_mask!=0x00ff00 ||
3733 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3734 goto notsupported;
3735 } else if (rDst==bmpImage->red_mask) {
3736 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3737 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3738 X11DRV_DIB_Convert_0888_to_888_asis
3739 (dstwidth,lines,
3740 srcbits,-bmpImage->bytes_per_line,
3741 dstbits,linebytes);
3742 } else {
3743 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3744 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3745 X11DRV_DIB_Convert_0888_to_888_reverse
3746 (dstwidth,lines,
3747 srcbits,-bmpImage->bytes_per_line,
3748 dstbits,linebytes);
3750 break;
3753 case 15:
3754 case 16:
3756 const char* srcbits;
3758 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3760 if (bmpImage->green_mask==0x03e0) {
3761 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
3762 (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3763 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
3764 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
3765 X11DRV_DIB_Convert_555_to_888_asis
3766 (dstwidth,lines,
3767 srcbits,-bmpImage->bytes_per_line,
3768 dstbits,linebytes);
3769 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
3770 (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
3771 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
3772 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
3773 X11DRV_DIB_Convert_555_to_888_reverse
3774 (dstwidth,lines,
3775 srcbits,-bmpImage->bytes_per_line,
3776 dstbits,linebytes);
3777 } else {
3778 goto notsupported;
3780 } else if (bmpImage->green_mask==0x07e0) {
3781 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
3782 (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
3783 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
3784 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
3785 X11DRV_DIB_Convert_565_to_888_asis
3786 (dstwidth,lines,
3787 srcbits,-bmpImage->bytes_per_line,
3788 dstbits,linebytes);
3789 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
3790 (bDst==0xff && bmpImage->blue_mask==0xf800)) {
3791 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
3792 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
3793 X11DRV_DIB_Convert_565_to_888_reverse
3794 (dstwidth,lines,
3795 srcbits,-bmpImage->bytes_per_line,
3796 dstbits,linebytes);
3797 } else {
3798 goto notsupported;
3800 } else {
3801 goto notsupported;
3804 break;
3806 case 1:
3807 case 4:
3808 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3809 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
3810 BYTE* dstbyte;
3812 /* Windows only supports one 24bpp DIB format: rgb 888 */
3813 for (h = lines - 1; h >= 0; h--) {
3814 dstbyte=dstbits;
3815 for (x = 0; x < dstwidth; x++) {
3816 PALETTEENTRY srcval;
3817 srcval=srccolors[XGetPixel(bmpImage, x, h)];
3818 dstbyte[0]=srcval.peBlue;
3819 dstbyte[1]=srcval.peGreen;
3820 dstbyte[2]=srcval.peRed;
3821 dstbyte+=3;
3823 dstbits += linebytes;
3825 } else {
3826 goto notsupported;
3828 break;
3830 case 8:
3831 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors) {
3832 /* ==== pal 8 bmp -> rgb 888 dib ==== */
3833 const void* srcbits;
3834 const BYTE* srcpixel;
3835 BYTE* dstbyte;
3837 /* Windows only supports one 24bpp DIB format: rgb 888 */
3838 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3839 for (h = lines - 1; h >= 0; h--) {
3840 srcpixel=srcbits;
3841 dstbyte=dstbits;
3842 for (x = 0; x < dstwidth; x++ ) {
3843 PALETTEENTRY srcval;
3844 srcval=srccolors[(int)*srcpixel++];
3845 dstbyte[0]=srcval.peBlue;
3846 dstbyte[1]=srcval.peGreen;
3847 dstbyte[2]=srcval.peRed;
3848 dstbyte+=3;
3850 srcbits -= bmpImage->bytes_per_line;
3851 dstbits += linebytes;
3853 } else {
3854 goto notsupported;
3856 break;
3858 default:
3859 notsupported:
3861 /* ==== any bmp format -> 888 dib ==== */
3862 BYTE* dstbyte;
3864 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
3865 bmpImage->depth, bmpImage->red_mask,
3866 bmpImage->green_mask, bmpImage->blue_mask,
3867 rDst, gDst, bDst );
3869 /* Windows only supports one 24bpp DIB format: rgb 888 */
3870 for (h = lines - 1; h >= 0; h--) {
3871 dstbyte=dstbits;
3872 for (x = 0; x < dstwidth; x++) {
3873 COLORREF srcval=X11DRV_PALETTE_ToLogical
3874 (XGetPixel( bmpImage, x, h ));
3875 dstbyte[0]=GetBValue(srcval);
3876 dstbyte[1]=GetGValue(srcval);
3877 dstbyte[2]=GetRValue(srcval);
3878 dstbyte+=3;
3880 dstbits += linebytes;
3883 break;
3888 /***********************************************************************
3889 * X11DRV_DIB_SetImageBits_32
3891 * SetDIBits for a 32-bit deep DIB.
3893 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
3894 DWORD srcwidth, DWORD dstwidth, int left,
3895 DC *dc,
3896 DWORD rSrc, DWORD gSrc, DWORD bSrc,
3897 XImage *bmpImage,
3898 DWORD linebytes)
3900 DWORD x, *ptr;
3901 int h;
3903 if (lines < 0 )
3905 lines = -lines;
3906 srcbits = srcbits + ( linebytes * (lines-1) );
3907 linebytes = -linebytes;
3910 ptr = (DWORD *) srcbits + left;
3912 switch (bmpImage->depth)
3914 case 24:
3915 if (bmpImage->bits_per_pixel==24) {
3916 char* dstbits;
3918 srcbits=srcbits+left*4;
3919 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3921 if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
3922 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
3923 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
3924 X11DRV_DIB_Convert_0888_to_888_asis
3925 (dstwidth,lines,
3926 srcbits,linebytes,
3927 dstbits,-bmpImage->bytes_per_line);
3928 } else if (bmpImage->green_mask!=0x00ff00 ||
3929 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3930 goto notsupported;
3931 /* the tests below assume sane bmpImage masks */
3932 } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
3933 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
3934 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
3935 X11DRV_DIB_Convert_0888_to_888_reverse
3936 (dstwidth,lines,
3937 srcbits,linebytes,
3938 dstbits,-bmpImage->bytes_per_line);
3939 } else if (bmpImage->blue_mask==0xff) {
3940 /* ==== any 0888 dib -> rgb 888 bmp ==== */
3941 X11DRV_DIB_Convert_any0888_to_rgb888
3942 (dstwidth,lines,
3943 srcbits,linebytes,
3944 rSrc,gSrc,bSrc,
3945 dstbits,-bmpImage->bytes_per_line);
3946 } else {
3947 /* ==== any 0888 dib -> bgr 888 bmp ==== */
3948 X11DRV_DIB_Convert_any0888_to_bgr888
3949 (dstwidth,lines,
3950 srcbits,linebytes,
3951 rSrc,gSrc,bSrc,
3952 dstbits,-bmpImage->bytes_per_line);
3954 break;
3956 /* fall through */
3958 case 32:
3960 char* dstbits;
3962 srcbits=srcbits+left*4;
3963 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3965 if (gSrc==bmpImage->green_mask) {
3966 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
3967 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
3968 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
3969 X11DRV_DIB_Convert_any_asis
3970 (dstwidth,lines,4,
3971 srcbits,linebytes,
3972 dstbits,-bmpImage->bytes_per_line);
3973 } else if (bmpImage->green_mask!=0x00ff00 ||
3974 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3975 goto notsupported;
3976 /* the tests below assume sane bmpImage masks */
3977 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
3978 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
3979 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
3980 X11DRV_DIB_Convert_0888_reverse
3981 (dstwidth,lines,
3982 srcbits,linebytes,
3983 dstbits,-bmpImage->bytes_per_line);
3984 } else {
3985 /* ==== any 0888 dib -> any 0888 bmp ==== */
3986 X11DRV_DIB_Convert_0888_any
3987 (dstwidth,lines,
3988 srcbits,linebytes,
3989 rSrc,gSrc,bSrc,
3990 dstbits,-bmpImage->bytes_per_line,
3991 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
3993 } else if (bmpImage->green_mask!=0x00ff00 ||
3994 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3995 goto notsupported;
3996 /* the tests below assume sane bmpImage masks */
3997 } else {
3998 /* ==== any 0888 dib -> any 0888 bmp ==== */
3999 X11DRV_DIB_Convert_0888_any
4000 (dstwidth,lines,
4001 srcbits,linebytes,
4002 rSrc,gSrc,bSrc,
4003 dstbits,-bmpImage->bytes_per_line,
4004 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4007 break;
4009 case 15:
4010 case 16:
4012 char* dstbits;
4014 srcbits=srcbits+left*4;
4015 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
4017 if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
4018 if (bmpImage->green_mask==0x03e0) {
4019 if (bmpImage->red_mask==0x7f00) {
4020 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
4021 X11DRV_DIB_Convert_0888_to_555_asis
4022 (dstwidth,lines,
4023 srcbits,linebytes,
4024 dstbits,-bmpImage->bytes_per_line);
4025 } else if (bmpImage->blue_mask==0x7f00) {
4026 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
4027 X11DRV_DIB_Convert_0888_to_555_reverse
4028 (dstwidth,lines,
4029 srcbits,linebytes,
4030 dstbits,-bmpImage->bytes_per_line);
4031 } else {
4032 goto notsupported;
4034 } else if (bmpImage->green_mask==0x07e0) {
4035 if (bmpImage->red_mask==0xf800) {
4036 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
4037 X11DRV_DIB_Convert_0888_to_565_asis
4038 (dstwidth,lines,
4039 srcbits,linebytes,
4040 dstbits,-bmpImage->bytes_per_line);
4041 } else if (bmpImage->blue_mask==0xf800) {
4042 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
4043 X11DRV_DIB_Convert_0888_to_565_reverse
4044 (dstwidth,lines,
4045 srcbits,linebytes,
4046 dstbits,-bmpImage->bytes_per_line);
4047 } else {
4048 goto notsupported;
4050 } else {
4051 goto notsupported;
4053 } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
4054 if (bmpImage->green_mask==0x03e0) {
4055 if (bmpImage->blue_mask==0x7f00) {
4056 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
4057 X11DRV_DIB_Convert_0888_to_555_asis
4058 (dstwidth,lines,
4059 srcbits,linebytes,
4060 dstbits,-bmpImage->bytes_per_line);
4061 } else if (bmpImage->red_mask==0x7f00) {
4062 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
4063 X11DRV_DIB_Convert_0888_to_555_reverse
4064 (dstwidth,lines,
4065 srcbits,linebytes,
4066 dstbits,-bmpImage->bytes_per_line);
4067 } else {
4068 goto notsupported;
4070 } else if (bmpImage->green_mask==0x07e0) {
4071 if (bmpImage->blue_mask==0xf800) {
4072 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
4073 X11DRV_DIB_Convert_0888_to_565_asis
4074 (dstwidth,lines,
4075 srcbits,linebytes,
4076 dstbits,-bmpImage->bytes_per_line);
4077 } else if (bmpImage->red_mask==0xf800) {
4078 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
4079 X11DRV_DIB_Convert_0888_to_565_reverse
4080 (dstwidth,lines,
4081 srcbits,linebytes,
4082 dstbits,-bmpImage->bytes_per_line);
4083 } else {
4084 goto notsupported;
4086 } else {
4087 goto notsupported;
4089 } else {
4090 if (bmpImage->green_mask==0x03e0 &&
4091 (bmpImage->red_mask==0x7f00 ||
4092 bmpImage->blue_mask==0x7f00)) {
4093 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
4094 X11DRV_DIB_Convert_any0888_to_5x5
4095 (dstwidth,lines,
4096 srcbits,linebytes,
4097 rSrc,gSrc,bSrc,
4098 dstbits,-bmpImage->bytes_per_line,
4099 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4100 } else if (bmpImage->green_mask==0x07e0 &&
4101 (bmpImage->red_mask==0xf800 ||
4102 bmpImage->blue_mask==0xf800)) {
4103 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
4104 X11DRV_DIB_Convert_any0888_to_5x5
4105 (dstwidth,lines,
4106 srcbits,linebytes,
4107 rSrc,gSrc,bSrc,
4108 dstbits,-bmpImage->bytes_per_line,
4109 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4110 } else {
4111 goto notsupported;
4115 break;
4117 default:
4118 notsupported:
4119 WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
4120 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
4121 bmpImage->green_mask, bmpImage->blue_mask );
4122 /* fall through */
4123 case 1:
4124 case 4:
4125 case 8:
4127 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
4128 const DWORD* srcpixel;
4129 int rShift,gShift,bShift;
4131 rShift=X11DRV_DIB_MaskToShift(rSrc);
4132 gShift=X11DRV_DIB_MaskToShift(gSrc);
4133 bShift=X11DRV_DIB_MaskToShift(bSrc);
4134 srcbits+=left*4;
4135 for (h = lines - 1; h >= 0; h--) {
4136 srcpixel=(const DWORD*)srcbits;
4137 for (x = left; x < dstwidth+left; x++) {
4138 DWORD srcvalue;
4139 BYTE red,green,blue;
4140 srcvalue=*srcpixel++;
4141 red= (srcvalue >> rShift) & 0xff;
4142 green=(srcvalue >> gShift) & 0xff;
4143 blue= (srcvalue >> bShift) & 0xff;
4144 XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
4145 (dc, RGB(red,green,blue)));
4147 srcbits += linebytes;
4150 break;
4155 /***********************************************************************
4156 * X11DRV_DIB_GetImageBits_32
4158 * GetDIBits for an 32-bit deep DIB.
4160 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
4161 DWORD dstwidth, DWORD srcwidth,
4162 PALETTEENTRY *srccolors,
4163 DWORD rDst, DWORD gDst, DWORD bDst,
4164 XImage *bmpImage, DWORD linebytes )
4166 DWORD x;
4167 int h;
4168 BYTE *bits;
4170 if (lines < 0 )
4172 lines = -lines;
4173 dstbits = dstbits + ( linebytes * (lines-1) );
4174 linebytes = -linebytes;
4177 bits = dstbits;
4179 switch (bmpImage->depth)
4181 case 24:
4182 if (bmpImage->bits_per_pixel==24) {
4183 const void* srcbits;
4185 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4187 if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
4188 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
4189 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
4190 X11DRV_DIB_Convert_888_to_0888_asis
4191 (dstwidth,lines,
4192 srcbits,-bmpImage->bytes_per_line,
4193 dstbits,linebytes);
4194 } else if (bmpImage->green_mask!=0x00ff00 ||
4195 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4196 goto notsupported;
4197 /* the tests below assume sane bmpImage masks */
4198 } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
4199 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
4200 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
4201 X11DRV_DIB_Convert_888_to_0888_reverse
4202 (dstwidth,lines,
4203 srcbits,-bmpImage->bytes_per_line,
4204 dstbits,linebytes);
4205 } else if (bmpImage->blue_mask==0xff) {
4206 /* ==== rgb 888 bmp -> any 0888 dib ==== */
4207 X11DRV_DIB_Convert_rgb888_to_any0888
4208 (dstwidth,lines,
4209 srcbits,-bmpImage->bytes_per_line,
4210 dstbits,linebytes,
4211 rDst,gDst,bDst);
4212 } else {
4213 /* ==== bgr 888 bmp -> any 0888 dib ==== */
4214 X11DRV_DIB_Convert_bgr888_to_any0888
4215 (dstwidth,lines,
4216 srcbits,-bmpImage->bytes_per_line,
4217 dstbits,linebytes,
4218 rDst,gDst,bDst);
4220 break;
4222 /* fall through */
4224 case 32:
4226 const char* srcbits;
4228 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4230 if (gDst==bmpImage->green_mask) {
4231 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
4232 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
4233 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
4234 X11DRV_DIB_Convert_any_asis
4235 (dstwidth,lines,4,
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 && bDst==bmpImage->red_mask) {
4243 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
4244 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
4245 X11DRV_DIB_Convert_0888_reverse
4246 (dstwidth,lines,
4247 srcbits,-bmpImage->bytes_per_line,
4248 dstbits,linebytes);
4249 } else {
4250 /* ==== any 0888 bmp -> any 0888 dib ==== */
4251 X11DRV_DIB_Convert_0888_any
4252 (dstwidth,lines,
4253 srcbits,-bmpImage->bytes_per_line,
4254 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4255 dstbits,linebytes,
4256 rDst,gDst,bDst);
4258 } else if (bmpImage->green_mask!=0x00ff00 ||
4259 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4260 goto notsupported;
4261 /* the tests below assume sane bmpImage masks */
4262 } else {
4263 /* ==== any 0888 bmp -> any 0888 dib ==== */
4264 X11DRV_DIB_Convert_0888_any
4265 (dstwidth,lines,
4266 srcbits,-bmpImage->bytes_per_line,
4267 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4268 dstbits,linebytes,
4269 rDst,gDst,bDst);
4272 break;
4274 case 15:
4275 case 16:
4277 const char* srcbits;
4279 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4281 if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
4282 if (bmpImage->green_mask==0x03e0) {
4283 if (bmpImage->red_mask==0x7f00) {
4284 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
4285 X11DRV_DIB_Convert_555_to_0888_asis
4286 (dstwidth,lines,
4287 srcbits,-bmpImage->bytes_per_line,
4288 dstbits,linebytes);
4289 } else if (bmpImage->blue_mask==0x7f00) {
4290 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
4291 X11DRV_DIB_Convert_555_to_0888_reverse
4292 (dstwidth,lines,
4293 srcbits,-bmpImage->bytes_per_line,
4294 dstbits,linebytes);
4295 } else {
4296 goto notsupported;
4298 } else if (bmpImage->green_mask==0x07e0) {
4299 if (bmpImage->red_mask==0xf800) {
4300 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
4301 X11DRV_DIB_Convert_565_to_0888_asis
4302 (dstwidth,lines,
4303 srcbits,-bmpImage->bytes_per_line,
4304 dstbits,linebytes);
4305 } else if (bmpImage->blue_mask==0xf800) {
4306 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
4307 X11DRV_DIB_Convert_565_to_0888_reverse
4308 (dstwidth,lines,
4309 srcbits,-bmpImage->bytes_per_line,
4310 dstbits,linebytes);
4311 } else {
4312 goto notsupported;
4314 } else {
4315 goto notsupported;
4317 } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
4318 if (bmpImage->green_mask==0x03e0) {
4319 if (bmpImage->blue_mask==0x7f00) {
4320 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
4321 X11DRV_DIB_Convert_555_to_0888_asis
4322 (dstwidth,lines,
4323 srcbits,-bmpImage->bytes_per_line,
4324 dstbits,linebytes);
4325 } else if (bmpImage->red_mask==0x7f00) {
4326 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
4327 X11DRV_DIB_Convert_555_to_0888_reverse
4328 (dstwidth,lines,
4329 srcbits,-bmpImage->bytes_per_line,
4330 dstbits,linebytes);
4331 } else {
4332 goto notsupported;
4334 } else if (bmpImage->green_mask==0x07e0) {
4335 if (bmpImage->blue_mask==0xf800) {
4336 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
4337 X11DRV_DIB_Convert_565_to_0888_asis
4338 (dstwidth,lines,
4339 srcbits,-bmpImage->bytes_per_line,
4340 dstbits,linebytes);
4341 } else if (bmpImage->red_mask==0xf800) {
4342 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
4343 X11DRV_DIB_Convert_565_to_0888_reverse
4344 (dstwidth,lines,
4345 srcbits,-bmpImage->bytes_per_line,
4346 dstbits,linebytes);
4347 } else {
4348 goto notsupported;
4350 } else {
4351 goto notsupported;
4353 } else {
4354 if (bmpImage->green_mask==0x03e0 &&
4355 (bmpImage->red_mask==0x7f00 ||
4356 bmpImage->blue_mask==0x7f00)) {
4357 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
4358 X11DRV_DIB_Convert_5x5_to_any0888
4359 (dstwidth,lines,
4360 srcbits,-bmpImage->bytes_per_line,
4361 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4362 dstbits,linebytes,
4363 rDst,gDst,bDst);
4364 } else if (bmpImage->green_mask==0x07e0 &&
4365 (bmpImage->red_mask==0xf800 ||
4366 bmpImage->blue_mask==0xf800)) {
4367 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
4368 X11DRV_DIB_Convert_5x5_to_any0888
4369 (dstwidth,lines,
4370 srcbits,-bmpImage->bytes_per_line,
4371 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4372 dstbits,linebytes,
4373 rDst,gDst,bDst);
4374 } else {
4375 goto notsupported;
4379 break;
4381 case 1:
4382 case 4:
4383 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4384 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
4385 int rShift,gShift,bShift;
4386 DWORD* dstpixel;
4388 rShift=X11DRV_DIB_MaskToShift(rDst);
4389 gShift=X11DRV_DIB_MaskToShift(gDst);
4390 bShift=X11DRV_DIB_MaskToShift(bDst);
4391 for (h = lines - 1; h >= 0; h--) {
4392 dstpixel=(DWORD*)dstbits;
4393 for (x = 0; x < dstwidth; x++) {
4394 PALETTEENTRY srcval;
4395 srcval = srccolors[XGetPixel(bmpImage, x, h)];
4396 *dstpixel++=(srcval.peRed << rShift) |
4397 (srcval.peGreen << gShift) |
4398 (srcval.peBlue << bShift);
4400 dstbits += linebytes;
4402 } else {
4403 goto notsupported;
4405 break;
4407 case 8:
4408 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4409 /* ==== pal 8 bmp -> any 0888 dib ==== */
4410 int rShift,gShift,bShift;
4411 const void* srcbits;
4412 const BYTE* srcpixel;
4413 DWORD* dstpixel;
4415 rShift=X11DRV_DIB_MaskToShift(rDst);
4416 gShift=X11DRV_DIB_MaskToShift(gDst);
4417 bShift=X11DRV_DIB_MaskToShift(bDst);
4418 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4419 for (h = lines - 1; h >= 0; h--) {
4420 srcpixel=srcbits;
4421 dstpixel=(DWORD*)dstbits;
4422 for (x = 0; x < dstwidth; x++) {
4423 PALETTEENTRY srcval;
4424 srcval=srccolors[(int)*srcpixel++];
4425 *dstpixel++=(srcval.peRed << rShift) |
4426 (srcval.peGreen << gShift) |
4427 (srcval.peBlue << bShift);
4429 srcbits -= bmpImage->bytes_per_line;
4430 dstbits += linebytes;
4432 } else {
4433 goto notsupported;
4435 break;
4437 default:
4438 notsupported:
4440 /* ==== any bmp format -> any 0888 dib ==== */
4441 int rShift,gShift,bShift;
4442 DWORD* dstpixel;
4444 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
4445 bmpImage->depth, bmpImage->red_mask,
4446 bmpImage->green_mask, bmpImage->blue_mask,
4447 rDst,gDst,bDst);
4449 rShift=X11DRV_DIB_MaskToShift(rDst);
4450 gShift=X11DRV_DIB_MaskToShift(gDst);
4451 bShift=X11DRV_DIB_MaskToShift(bDst);
4452 for (h = lines - 1; h >= 0; h--) {
4453 dstpixel=(DWORD*)dstbits;
4454 for (x = 0; x < dstwidth; x++) {
4455 COLORREF srcval;
4456 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
4457 *dstpixel++=(GetRValue(srcval) << rShift) |
4458 (GetGValue(srcval) << gShift) |
4459 (GetBValue(srcval) << bShift);
4461 dstbits += linebytes;
4464 break;
4468 /***********************************************************************
4469 * X11DRV_DIB_SetImageBits
4471 * Transfer the bits to an X image.
4472 * Helper function for SetDIBits() and SetDIBitsToDevice().
4474 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4476 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4477 XImage *bmpImage;
4479 wine_tsx11_lock();
4480 if (descr->image)
4481 bmpImage = descr->image;
4482 else {
4483 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4484 descr->infoWidth, lines, 32, 0 );
4485 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4486 if(bmpImage->data == NULL) {
4487 ERR("Out of memory!\n");
4488 XDestroyImage( bmpImage );
4489 wine_tsx11_unlock();
4490 return lines;
4494 TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
4495 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4496 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
4497 bmpImage->depth,bmpImage->bits_per_pixel,
4498 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4500 /* Transfer the pixels */
4501 switch(descr->infoBpp)
4503 case 1:
4504 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
4505 descr->width, descr->xSrc, (int *)(descr->colorMap),
4506 bmpImage, descr->dibpitch );
4507 break;
4508 case 4:
4509 if (descr->compression) {
4510 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4511 descr->width, descr->height, AllPlanes, ZPixmap,
4512 bmpImage, descr->xSrc, descr->ySrc );
4514 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
4515 descr->infoWidth, descr->width,
4516 descr->xSrc, (int *)(descr->colorMap),
4517 bmpImage );
4518 } else
4519 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
4520 descr->infoWidth, descr->width,
4521 descr->xSrc, (int*)(descr->colorMap),
4522 bmpImage, descr->dibpitch );
4523 break;
4524 case 8:
4525 if (descr->compression) {
4526 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4527 descr->width, descr->height, AllPlanes, ZPixmap,
4528 bmpImage, descr->xSrc, descr->ySrc );
4529 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
4530 descr->infoWidth, descr->width,
4531 descr->xSrc, (int *)(descr->colorMap),
4532 bmpImage );
4533 } else
4534 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
4535 descr->infoWidth, descr->width,
4536 descr->xSrc, (int *)(descr->colorMap),
4537 bmpImage, descr->dibpitch );
4538 break;
4539 case 15:
4540 case 16:
4541 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
4542 descr->infoWidth, descr->width,
4543 descr->xSrc, descr->dc,
4544 descr->rMask, descr->gMask, descr->bMask,
4545 bmpImage, descr->dibpitch);
4546 break;
4547 case 24:
4548 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
4549 descr->infoWidth, descr->width,
4550 descr->xSrc, descr->dc,
4551 descr->rMask, descr->gMask, descr->bMask,
4552 bmpImage, descr->dibpitch);
4553 break;
4554 case 32:
4555 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
4556 descr->infoWidth, descr->width,
4557 descr->xSrc, descr->dc,
4558 descr->rMask, descr->gMask, descr->bMask,
4559 bmpImage, descr->dibpitch);
4560 break;
4561 default:
4562 WARN("(%d): Invalid depth\n", descr->infoBpp );
4563 break;
4566 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
4567 descr->drawable, descr->gc, bmpImage,
4568 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4569 descr->width, descr->height);
4570 #ifdef HAVE_LIBXXSHM
4571 if (descr->useShm)
4573 XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4574 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4575 descr->width, descr->height, FALSE );
4576 XSync( gdi_display, 0 );
4578 else
4579 #endif
4580 XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4581 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4582 descr->width, descr->height );
4584 if (!descr->image) XDestroyImage( bmpImage );
4585 wine_tsx11_unlock();
4586 return lines;
4589 /***********************************************************************
4590 * X11DRV_DIB_GetImageBits
4592 * Transfer the bits from an X image.
4594 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4596 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4597 XImage *bmpImage;
4599 wine_tsx11_lock();
4600 if (descr->image)
4601 bmpImage = descr->image;
4602 else {
4603 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4604 descr->infoWidth, lines, 32, 0 );
4605 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4606 if(bmpImage->data == NULL) {
4607 ERR("Out of memory!\n");
4608 XDestroyImage( bmpImage );
4609 wine_tsx11_unlock();
4610 return lines;
4614 if (descr->useShm)
4616 int saveRed, saveGreen, saveBlue;
4618 TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
4619 gdi_display, descr->drawable, bmpImage,
4620 descr->xSrc, descr->ySrc, AllPlanes);
4622 /* We must save and restore the bmpImage's masks in order
4623 * to preserve them across the call to XShmGetImage, which
4624 * decides to eleminate them since it doesn't happen to know
4625 * what the format of the image is supposed to be, even though
4626 * we do. */
4627 saveRed = bmpImage->red_mask;
4628 saveBlue= bmpImage->blue_mask;
4629 saveGreen = bmpImage->green_mask;
4631 XShmGetImage( gdi_display, descr->drawable, bmpImage,
4632 descr->xSrc, descr->ySrc, AllPlanes);
4634 bmpImage->red_mask = saveRed;
4635 bmpImage->blue_mask = saveBlue;
4636 bmpImage->green_mask = saveGreen;
4638 else
4640 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
4641 gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
4642 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
4643 XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
4644 descr->width, lines, AllPlanes, ZPixmap,
4645 bmpImage, descr->xDest, descr->yDest );
4648 TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
4649 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4650 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
4651 bmpImage->depth,bmpImage->bits_per_pixel,
4652 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4653 /* Transfer the pixels */
4654 switch(descr->infoBpp)
4656 case 1:
4657 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
4658 descr->infoWidth, descr->width,
4659 descr->colorMap, descr->palentry,
4660 bmpImage, descr->dibpitch );
4661 break;
4663 case 4:
4664 if (descr->compression)
4665 FIXME("Compression not yet supported!\n");
4666 else
4667 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
4668 descr->infoWidth, descr->width,
4669 descr->colorMap, descr->palentry,
4670 bmpImage, descr->dibpitch );
4671 break;
4673 case 8:
4674 if (descr->compression)
4675 FIXME("Compression not yet supported!\n");
4676 else
4677 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
4678 descr->infoWidth, descr->width,
4679 descr->colorMap, descr->palentry,
4680 bmpImage, descr->dibpitch );
4681 break;
4682 case 15:
4683 case 16:
4684 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
4685 descr->infoWidth,descr->width,
4686 descr->palentry,
4687 descr->rMask, descr->gMask, descr->bMask,
4688 bmpImage, descr->dibpitch );
4689 break;
4691 case 24:
4692 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
4693 descr->infoWidth,descr->width,
4694 descr->palentry,
4695 descr->rMask, descr->gMask, descr->bMask,
4696 bmpImage, descr->dibpitch);
4697 break;
4699 case 32:
4700 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
4701 descr->infoWidth, descr->width,
4702 descr->palentry,
4703 descr->rMask, descr->gMask, descr->bMask,
4704 bmpImage, descr->dibpitch);
4705 break;
4707 default:
4708 WARN("(%d): Invalid depth\n", descr->infoBpp );
4709 break;
4712 if (!descr->image) XDestroyImage( bmpImage );
4713 wine_tsx11_unlock();
4714 return lines;
4717 /*************************************************************************
4718 * X11DRV_SetDIBitsToDevice
4721 INT X11DRV_SetDIBitsToDevice( DC *dc, INT xDest, INT yDest, DWORD cx,
4722 DWORD cy, INT xSrc, INT ySrc,
4723 UINT startscan, UINT lines, LPCVOID bits,
4724 const BITMAPINFO *info, UINT coloruse )
4726 X11DRV_DIB_IMAGEBITS_DESCR descr;
4727 DWORD width, oldcy = cy;
4728 INT result;
4729 int height, tmpheight;
4730 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
4733 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
4734 &descr.infoBpp, &descr.compression ) == -1)
4735 return 0;
4736 tmpheight = height;
4737 if (height < 0) height = -height;
4738 if (!lines || (startscan >= height)) return 0;
4739 if (startscan + lines > height) lines = height - startscan;
4740 if (ySrc < startscan) ySrc = startscan;
4741 else if (ySrc >= startscan + lines) return 0;
4742 if (xSrc >= width) return 0;
4743 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
4744 if (xSrc + cx >= width) cx = width - xSrc;
4745 if (!cx || !cy) return 0;
4747 X11DRV_SetupGCForText( dc ); /* To have the correct colors */
4748 TSXSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
4750 switch (descr.infoBpp)
4752 case 1:
4753 case 4:
4754 case 8:
4755 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4756 coloruse == DIB_PAL_COLORS ? dc : NULL, coloruse,
4757 dc->bitsPerPixel, info, &descr.nColorMap );
4758 if (!descr.colorMap) return 0;
4759 descr.rMask = descr.gMask = descr.bMask = 0;
4760 break;
4761 case 15:
4762 case 16:
4763 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4764 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4765 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4766 descr.colorMap = 0;
4767 break;
4769 case 24:
4770 case 32:
4771 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
4772 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4773 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4774 descr.colorMap = 0;
4775 break;
4778 descr.dc = dc;
4779 descr.bits = bits;
4780 descr.image = NULL;
4781 descr.palentry = NULL;
4782 descr.lines = tmpheight >= 0 ? lines : -lines;
4783 descr.infoWidth = width;
4784 descr.depth = dc->bitsPerPixel;
4785 descr.drawable = physDev->drawable;
4786 descr.gc = physDev->gc;
4787 descr.xSrc = xSrc;
4788 descr.ySrc = tmpheight >= 0 ? lines-(ySrc-startscan)-cy+(oldcy-cy)
4789 : ySrc - startscan;
4790 descr.xDest = dc->DCOrgX + XLPTODP( dc, xDest );
4791 descr.yDest = dc->DCOrgY + YLPTODP( dc, yDest ) +
4792 (tmpheight >= 0 ? oldcy-cy : 0);
4793 descr.width = cx;
4794 descr.height = cy;
4795 descr.useShm = FALSE;
4796 descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
4798 result = X11DRV_DIB_SetImageBits( &descr );
4800 if (descr.infoBpp <= 8)
4801 HeapFree(GetProcessHeap(), 0, descr.colorMap);
4802 return result;
4805 /***********************************************************************
4806 * X11DRV_DIB_SetDIBits
4808 INT X11DRV_DIB_SetDIBits(
4809 BITMAPOBJ *bmp, DC *dc, UINT startscan,
4810 UINT lines, LPCVOID bits, const BITMAPINFO *info,
4811 UINT coloruse, HBITMAP hbitmap)
4813 X11DRV_DIB_IMAGEBITS_DESCR descr;
4814 int height, tmpheight;
4815 INT result;
4817 descr.dc = dc;
4819 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
4820 &descr.infoBpp, &descr.compression ) == -1)
4821 return 0;
4823 tmpheight = height;
4824 if (height < 0) height = -height;
4825 if (!lines || (startscan >= height))
4826 return 0;
4828 if (startscan + lines > height) lines = height - startscan;
4830 switch (descr.infoBpp)
4832 case 1:
4833 case 4:
4834 case 8:
4835 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4836 coloruse == DIB_PAL_COLORS ? descr.dc : NULL, coloruse,
4837 bmp->bitmap.bmBitsPixel,
4838 info, &descr.nColorMap );
4839 if (!descr.colorMap) return 0;
4840 descr.rMask = descr.gMask = descr.bMask = 0;
4841 break;
4842 case 15:
4843 case 16:
4844 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4845 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4846 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4847 descr.colorMap = 0;
4848 break;
4850 case 24:
4851 case 32:
4852 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
4853 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4854 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4855 descr.colorMap = 0;
4856 break;
4858 default: break;
4861 /* HACK for now */
4862 if(!bmp->physBitmap)
4863 X11DRV_CreateBitmap(hbitmap);
4865 descr.bits = bits;
4866 descr.image = NULL;
4867 descr.palentry = NULL;
4868 descr.lines = tmpheight >= 0 ? lines : -lines;
4869 descr.depth = bmp->bitmap.bmBitsPixel;
4870 descr.drawable = (Pixmap)bmp->physBitmap;
4871 descr.gc = BITMAP_GC(bmp);
4872 descr.xSrc = 0;
4873 descr.ySrc = 0;
4874 descr.xDest = 0;
4875 descr.yDest = height - startscan - lines;
4876 descr.width = bmp->bitmap.bmWidth;
4877 descr.height = lines;
4878 descr.useShm = FALSE;
4879 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
4880 result = X11DRV_DIB_SetImageBits( &descr );
4882 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
4884 return result;
4887 /***********************************************************************
4888 * X11DRV_DIB_GetDIBits
4890 INT X11DRV_DIB_GetDIBits(
4891 BITMAPOBJ *bmp, DC *dc, UINT startscan,
4892 UINT lines, LPVOID bits, BITMAPINFO *info,
4893 UINT coloruse, HBITMAP hbitmap)
4895 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
4896 X11DRV_DIB_IMAGEBITS_DESCR descr;
4897 PALETTEOBJ * palette;
4898 int height;
4900 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
4901 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
4902 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
4903 startscan );
4905 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
4906 return 0;
4908 if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
4910 height = info->bmiHeader.biHeight;
4911 if (height < 0) height = -height;
4912 if( lines > height ) lines = height;
4913 /* Top-down images have a negative biHeight, the scanlines of theses images
4914 * were inverted in X11DRV_DIB_GetImageBits_xx
4915 * To prevent this we simply change the sign of lines
4916 * (the number of scan lines to copy).
4917 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
4919 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
4921 if( startscan >= bmp->bitmap.bmHeight )
4923 lines = 0;
4924 goto done;
4927 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
4928 &descr.infoBpp, &descr.compression ) == -1)
4930 lines = 0;
4931 goto done;
4934 switch (descr.infoBpp)
4936 case 1:
4937 case 4:
4938 case 8:
4939 descr.rMask= descr.gMask = descr.bMask = 0;
4940 break;
4941 case 15:
4942 case 16:
4943 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4944 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4945 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4946 break;
4947 case 24:
4948 case 32:
4949 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
4950 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4951 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4952 break;
4955 /* Hack for now */
4956 if(!bmp->physBitmap)
4957 X11DRV_CreateBitmap(hbitmap);
4960 descr.dc = dc;
4961 descr.palentry = palette->logpalette.palPalEntry;
4962 descr.bits = bits;
4963 descr.image = NULL;
4964 descr.lines = lines;
4965 descr.depth = bmp->bitmap.bmBitsPixel;
4966 descr.drawable = (Pixmap)bmp->physBitmap;
4967 descr.gc = BITMAP_GC(bmp);
4968 descr.width = bmp->bitmap.bmWidth;
4969 descr.height = bmp->bitmap.bmHeight;
4970 descr.colorMap = info->bmiColors;
4971 descr.xDest = 0;
4972 descr.yDest = 0;
4973 descr.xSrc = 0;
4975 if (descr.lines > 0)
4977 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
4979 else
4981 descr.ySrc = startscan;
4983 #ifdef HAVE_LIBXXSHM
4984 descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
4985 #else
4986 descr.useShm = FALSE;
4987 #endif
4988 descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
4989 : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
4991 X11DRV_DIB_GetImageBits( &descr );
4993 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
4994 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
4995 info->bmiHeader.biWidth,
4996 info->bmiHeader.biHeight,
4997 info->bmiHeader.biBitCount );
4999 info->bmiHeader.biCompression = 0;
5000 if (descr.compression == BI_BITFIELDS)
5002 *(DWORD *)info->bmiColors = descr.rMask;
5003 *((DWORD *)info->bmiColors+1) = descr.gMask;
5004 *((DWORD *)info->bmiColors+2) = descr.bMask;
5007 done:
5008 GDI_ReleaseObj( dc->hPalette );
5010 return lines;
5013 /***********************************************************************
5014 * DIB_DoProtectDIBSection
5016 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
5018 DIBSECTION *dib = bmp->dib;
5019 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
5020 : -dib->dsBm.bmHeight;
5021 /* use the biSizeImage data as the memory size only if we're dealing with a
5022 compressed image where the value is set. Otherwise, calculate based on
5023 width * height */
5024 INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
5025 ? dib->dsBmih.biSizeImage
5026 : dib->dsBm.bmWidthBytes * effHeight;
5027 DWORD old_prot;
5029 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
5030 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
5033 /***********************************************************************
5034 * X11DRV_DIB_DoUpdateDIBSection
5036 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
5037 void *colorMap, int nColorMap,
5038 Drawable dest,
5039 DWORD xSrc, DWORD ySrc,
5040 DWORD xDest, DWORD yDest,
5041 DWORD width, DWORD height)
5043 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5044 X11DRV_DIB_IMAGEBITS_DESCR descr;
5046 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
5047 &descr.infoBpp, &descr.compression ) == -1)
5048 return;
5050 descr.dc = NULL;
5051 descr.palentry = NULL;
5052 descr.image = dib->image;
5053 descr.colorMap = colorMap;
5054 descr.nColorMap = nColorMap;
5055 descr.bits = dib->dibSection.dsBm.bmBits;
5056 descr.depth = bmp->bitmap.bmBitsPixel;
5058 switch (descr.infoBpp)
5060 case 1:
5061 case 4:
5062 case 8:
5063 descr.rMask = descr.gMask = descr.bMask = 0;
5064 break;
5065 case 15:
5066 case 16:
5067 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
5068 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
5069 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
5070 break;
5072 case 24:
5073 case 32:
5074 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff0000;
5075 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x00ff00;
5076 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x0000ff;
5077 break;
5080 /* Hack for now */
5081 descr.drawable = dest;
5082 descr.gc = BITMAP_GC(bmp);
5083 descr.xSrc = xSrc;
5084 descr.ySrc = ySrc;
5085 descr.xDest = xDest;
5086 descr.yDest = yDest;
5087 descr.width = width;
5088 descr.height = height;
5089 #ifdef HAVE_LIBXXSHM
5090 descr.useShm = (dib->shminfo.shmid != -1);
5091 #else
5092 descr.useShm = FALSE;
5093 #endif
5094 descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
5096 if (toDIB)
5098 TRACE("Copying from Pixmap to DIB bits\n");
5099 X11DRV_DIB_GetImageBits( &descr );
5101 else
5103 TRACE("Copying from DIB bits to Pixmap\n");
5104 X11DRV_DIB_SetImageBits( &descr );
5108 /***********************************************************************
5109 * X11DRV_DIB_CopyDIBSection
5111 void X11DRV_DIB_CopyDIBSection(DC *dcSrc, DC *dcDst,
5112 DWORD xSrc, DWORD ySrc,
5113 DWORD xDest, DWORD yDest,
5114 DWORD width, DWORD height)
5116 BITMAPOBJ *bmp;
5117 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dcDst->physDev;
5118 int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
5120 TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", dcSrc, dcDst,
5121 xSrc, ySrc, xDest, yDest, width, height);
5122 /* this function is meant as an optimization for BitBlt,
5123 * not to be called otherwise */
5124 if (!(dcSrc->flags & DC_MEMORY)) {
5125 ERR("called for non-memory source DC!?\n");
5126 return;
5129 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
5130 if (!(bmp && bmp->dib)) {
5131 ERR("called for non-DIBSection!?\n");
5132 GDI_ReleaseObj( dcSrc->hBitmap );
5133 return;
5135 /* while BitBlt should already have made sure we only get
5136 * positive values, we should check for oversize values */
5137 if ((xSrc < bmp->bitmap.bmWidth) &&
5138 (ySrc < bmp->bitmap.bmHeight)) {
5139 if (xSrc + width > bmp->bitmap.bmWidth)
5140 width = bmp->bitmap.bmWidth - xSrc;
5141 if (ySrc + height > bmp->bitmap.bmHeight)
5142 height = bmp->bitmap.bmHeight - ySrc;
5143 /* if the source bitmap is 8bpp or less, we're supposed to use the
5144 * DC's palette for color conversion (not the DIB color table) */
5145 if (bmp->dib->dsBm.bmBitsPixel <= 8) {
5146 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5147 if ((!dcSrc->hPalette) ||
5148 (dcSrc->hPalette == GetStockObject(DEFAULT_PALETTE))) {
5149 /* HACK: no palette has been set in the source DC,
5150 * use the DIB colormap instead - this is necessary in some
5151 * cases since we need to do depth conversion in some places
5152 * where real Windows can just copy data straight over */
5153 colorMap = dib->colorMap;
5154 nColorMap = dib->nColorMap;
5155 } else {
5156 colorMap = X11DRV_DIB_BuildColorMap( dcSrc, (WORD)-1,
5157 bmp->dib->dsBm.bmBitsPixel,
5158 (BITMAPINFO*)&(bmp->dib->dsBmih),
5159 &nColorMap );
5160 if (colorMap) aColorMap = TRUE;
5163 /* perform the copy */
5164 X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
5165 physDev->drawable, xSrc, ySrc, xDest, yDest,
5166 width, height);
5167 /* free color mapping */
5168 if (aColorMap)
5169 HeapFree(GetProcessHeap(), 0, colorMap);
5171 GDI_ReleaseObj( dcSrc->hBitmap );
5174 /***********************************************************************
5175 * X11DRV_DIB_DoUpdateDIBSection
5177 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
5179 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5180 X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
5181 (Drawable)bmp->physBitmap, 0, 0, 0, 0,
5182 bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
5185 /***********************************************************************
5186 * X11DRV_DIB_FaultHandler
5188 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
5190 BITMAPOBJ *bmp;
5191 INT state;
5193 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
5194 if (!bmp) return FALSE;
5196 state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
5197 if (state != DIB_Status_InSync) {
5198 /* no way to tell whether app needs read or write yet,
5199 * try read first */
5200 X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
5201 } else {
5202 /* hm, apparently the app must have write access */
5203 X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
5205 X11DRV_DIB_Unlock(bmp, TRUE);
5207 GDI_ReleaseObj( (HBITMAP)res );
5208 return TRUE;
5211 /***********************************************************************
5212 * X11DRV_DIB_Coerce
5214 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
5216 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5217 INT ret = DIB_Status_None;
5219 if (dib) {
5220 EnterCriticalSection(&(dib->lock));
5221 ret = dib->status;
5222 switch (req) {
5223 case DIB_Status_GdiMod:
5224 /* GDI access - request to draw on pixmap */
5225 switch (dib->status)
5227 default:
5228 case DIB_Status_None:
5229 dib->p_status = DIB_Status_GdiMod;
5230 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5231 break;
5233 case DIB_Status_GdiMod:
5234 TRACE("GdiMod requested in status GdiMod\n" );
5235 break;
5237 case DIB_Status_InSync:
5238 TRACE("GdiMod requested in status InSync\n" );
5239 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5240 dib->status = DIB_Status_GdiMod;
5241 dib->p_status = DIB_Status_InSync;
5242 break;
5244 case DIB_Status_AuxMod:
5245 TRACE("GdiMod requested in status AuxMod\n" );
5246 if (lossy) dib->status = DIB_Status_GdiMod;
5247 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
5248 dib->p_status = DIB_Status_AuxMod;
5249 if (dib->status != DIB_Status_AppMod) {
5250 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5251 break;
5253 /* fall through if copy_aux() had to change to AppMod state */
5255 case DIB_Status_AppMod:
5256 TRACE("GdiMod requested in status AppMod\n" );
5257 if (!lossy) {
5258 /* make it readonly to avoid app changing data while we copy */
5259 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5260 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5262 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5263 dib->p_status = DIB_Status_AppMod;
5264 dib->status = DIB_Status_GdiMod;
5265 break;
5267 break;
5269 case DIB_Status_InSync:
5270 /* App access - request access to read DIB surface */
5271 /* (typically called from signal handler) */
5272 switch (dib->status)
5274 default:
5275 case DIB_Status_None:
5276 /* shouldn't happen from signal handler */
5277 break;
5279 case DIB_Status_AuxMod:
5280 TRACE("InSync requested in status AuxMod\n" );
5281 if (lossy) dib->status = DIB_Status_InSync;
5282 else {
5283 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5284 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
5286 if (dib->status != DIB_Status_GdiMod) {
5287 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5288 break;
5290 /* fall through if copy_aux() had to change to GdiMod state */
5292 case DIB_Status_GdiMod:
5293 TRACE("InSync requested in status GdiMod\n" );
5294 if (!lossy) {
5295 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5296 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5298 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5299 dib->status = DIB_Status_InSync;
5300 break;
5302 case DIB_Status_InSync:
5303 TRACE("InSync requested in status InSync\n" );
5304 /* shouldn't happen from signal handler */
5305 break;
5307 case DIB_Status_AppMod:
5308 TRACE("InSync requested in status AppMod\n" );
5309 /* no reason to do anything here, and this
5310 * shouldn't happen from signal handler */
5311 break;
5313 break;
5315 case DIB_Status_AppMod:
5316 /* App access - request access to write DIB surface */
5317 /* (typically called from signal handler) */
5318 switch (dib->status)
5320 default:
5321 case DIB_Status_None:
5322 /* shouldn't happen from signal handler */
5323 break;
5325 case DIB_Status_AuxMod:
5326 TRACE("AppMod requested in status AuxMod\n" );
5327 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5328 if (lossy) dib->status = DIB_Status_AppMod;
5329 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5330 if (dib->status != DIB_Status_GdiMod)
5331 break;
5332 /* fall through if copy_aux() had to change to GdiMod state */
5334 case DIB_Status_GdiMod:
5335 TRACE("AppMod requested in status GdiMod\n" );
5336 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5337 if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5338 dib->status = DIB_Status_AppMod;
5339 break;
5341 case DIB_Status_InSync:
5342 TRACE("AppMod requested in status InSync\n" );
5343 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5344 dib->status = DIB_Status_AppMod;
5345 break;
5347 case DIB_Status_AppMod:
5348 TRACE("AppMod requested in status AppMod\n" );
5349 /* shouldn't happen from signal handler */
5350 break;
5352 break;
5354 case DIB_Status_AuxMod:
5355 if (dib->status == DIB_Status_None) {
5356 dib->p_status = req;
5357 } else {
5358 if (dib->status != DIB_Status_AuxMod)
5359 dib->p_status = dib->status;
5360 dib->status = DIB_Status_AuxMod;
5362 break;
5363 /* it is up to the caller to do the copy/conversion, probably
5364 * using the return value to decide where to copy from */
5366 LeaveCriticalSection(&(dib->lock));
5368 return ret;
5371 /***********************************************************************
5372 * X11DRV_DIB_Lock
5374 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
5376 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5377 INT ret = DIB_Status_None;
5379 if (dib) {
5380 TRACE("Locking %p from thread %08lx\n", bmp, GetCurrentThreadId());
5381 EnterCriticalSection(&(dib->lock));
5382 ret = dib->status;
5383 if (req != DIB_Status_None)
5384 X11DRV_DIB_Coerce(bmp, req, lossy);
5386 return ret;
5389 /***********************************************************************
5390 * X11DRV_DIB_Unlock
5392 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
5394 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5396 if (dib) {
5397 switch (dib->status)
5399 default:
5400 case DIB_Status_None:
5401 /* in case anyone is wondering, this is the "signal handler doesn't
5402 * work" case, where we always have to be ready for app access */
5403 if (commit) {
5404 switch (dib->p_status)
5406 case DIB_Status_AuxMod:
5407 TRACE("Unlocking and syncing from AuxMod\n" );
5408 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5409 if (dib->status != DIB_Status_None) {
5410 dib->p_status = dib->status;
5411 dib->status = DIB_Status_None;
5413 if (dib->p_status != DIB_Status_GdiMod)
5414 break;
5415 /* fall through if copy_aux() had to change to GdiMod state */
5417 case DIB_Status_GdiMod:
5418 TRACE("Unlocking and syncing from GdiMod\n" );
5419 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5420 break;
5422 default:
5423 TRACE("Unlocking without needing to sync\n" );
5424 break;
5427 else TRACE("Unlocking with no changes\n");
5428 dib->p_status = DIB_Status_None;
5429 break;
5431 case DIB_Status_GdiMod:
5432 TRACE("Unlocking in status GdiMod\n" );
5433 /* DIB was protected in Coerce */
5434 if (!commit) {
5435 /* no commit, revert to InSync if applicable */
5436 if ((dib->p_status == DIB_Status_InSync) ||
5437 (dib->p_status == DIB_Status_AppMod)) {
5438 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5439 dib->status = DIB_Status_InSync;
5442 break;
5444 case DIB_Status_InSync:
5445 TRACE("Unlocking in status InSync\n" );
5446 /* DIB was already protected in Coerce */
5447 break;
5449 case DIB_Status_AppMod:
5450 TRACE("Unlocking in status AppMod\n" );
5451 /* DIB was already protected in Coerce */
5452 /* this case is ordinary only called from the signal handler,
5453 * so we don't bother to check for !commit */
5454 break;
5456 case DIB_Status_AuxMod:
5457 TRACE("Unlocking in status AuxMod\n" );
5458 if (commit) {
5459 /* DIB may need protection now */
5460 if ((dib->p_status == DIB_Status_InSync) ||
5461 (dib->p_status == DIB_Status_AppMod))
5462 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5463 } else {
5464 /* no commit, revert to previous state */
5465 if (dib->p_status != DIB_Status_None)
5466 dib->status = dib->p_status;
5467 /* no protections changed */
5469 dib->p_status = DIB_Status_None;
5470 break;
5472 LeaveCriticalSection(&(dib->lock));
5473 TRACE("Unlocked %p\n", bmp);
5477 /***********************************************************************
5478 * X11DRV_CoerceDIBSection2
5480 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5482 BITMAPOBJ *bmp;
5483 INT ret;
5485 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5486 if (!bmp) return DIB_Status_None;
5487 ret = X11DRV_DIB_Coerce(bmp, req, lossy);
5488 GDI_ReleaseObj( hBmp );
5489 return ret;
5492 /***********************************************************************
5493 * X11DRV_LockDIBSection2
5495 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5497 BITMAPOBJ *bmp;
5498 INT ret;
5500 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5501 if (!bmp) return DIB_Status_None;
5502 ret = X11DRV_DIB_Lock(bmp, req, lossy);
5503 GDI_ReleaseObj( hBmp );
5504 return ret;
5507 /***********************************************************************
5508 * X11DRV_UnlockDIBSection2
5510 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
5512 BITMAPOBJ *bmp;
5514 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5515 if (!bmp) return;
5516 X11DRV_DIB_Unlock(bmp, commit);
5517 GDI_ReleaseObj( hBmp );
5520 /***********************************************************************
5521 * X11DRV_CoerceDIBSection
5523 INT X11DRV_CoerceDIBSection(DC *dc, INT req, BOOL lossy)
5525 if (!dc) return DIB_Status_None;
5526 return X11DRV_CoerceDIBSection2( dc->hBitmap, req, lossy );
5529 /***********************************************************************
5530 * X11DRV_LockDIBSection
5532 INT X11DRV_LockDIBSection(DC *dc, INT req, BOOL lossy)
5534 if (!dc) return DIB_Status_None;
5535 if (!(dc->flags & DC_MEMORY)) return DIB_Status_None;
5537 return X11DRV_LockDIBSection2( dc->hBitmap, req, lossy );
5540 /***********************************************************************
5541 * X11DRV_UnlockDIBSection
5543 void X11DRV_UnlockDIBSection(DC *dc, BOOL commit)
5545 if (!dc) return;
5546 if (!(dc->flags & DC_MEMORY)) return;
5548 X11DRV_UnlockDIBSection2( dc->hBitmap, commit );
5552 #ifdef HAVE_LIBXXSHM
5553 /***********************************************************************
5554 * X11DRV_XShmErrorHandler
5557 static int XShmErrorHandler(Display *dpy, XErrorEvent *event)
5559 XShmErrorFlag = 1;
5560 return 0;
5563 /***********************************************************************
5564 * X11DRV_XShmCreateImage
5567 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
5568 XShmSegmentInfo* shminfo)
5570 int (*WineXHandler)(Display *, XErrorEvent *);
5571 XImage *image;
5573 wine_tsx11_lock();
5574 image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
5575 if (image)
5577 shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
5578 IPC_CREAT|0700);
5579 if( shminfo->shmid != -1 )
5581 shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
5582 if( shminfo->shmaddr != (char*)-1 )
5584 shminfo->readOnly = FALSE;
5585 if( XShmAttach( gdi_display, shminfo ) != 0)
5587 /* Reset the error flag */
5588 XShmErrorFlag = 0;
5589 WineXHandler = XSetErrorHandler(XShmErrorHandler);
5590 XSync( gdi_display, 0 );
5592 if (!XShmErrorFlag)
5594 shmctl(shminfo->shmid, IPC_RMID, 0);
5596 XSetErrorHandler(WineXHandler);
5597 wine_tsx11_unlock();
5598 return image; /* Success! */
5600 /* An error occured */
5601 XShmErrorFlag = 0;
5602 XSetErrorHandler(WineXHandler);
5604 shmdt(shminfo->shmaddr);
5606 shmctl(shminfo->shmid, IPC_RMID, 0);
5608 XFlush(gdi_display);
5609 XDestroyImage(image);
5610 image = NULL;
5612 wine_tsx11_unlock();
5613 return image;
5615 #endif /* HAVE_LIBXXSHM */
5618 /***********************************************************************
5619 * X11DRV_DIB_CreateDIBSection
5621 HBITMAP X11DRV_DIB_CreateDIBSection(
5622 DC *dc, BITMAPINFO *bmi, UINT usage,
5623 LPVOID *bits, HANDLE section,
5624 DWORD offset, DWORD ovr_pitch)
5626 HBITMAP res = 0;
5627 BITMAPOBJ *bmp = NULL;
5628 X11DRV_DIBSECTION *dib = NULL;
5629 int *colorMap = NULL;
5630 int nColorMap;
5632 /* Fill BITMAP32 structure with DIB data */
5633 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
5634 INT effHeight, totalSize;
5635 BITMAP bm;
5636 LPVOID mapBits = NULL;
5638 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
5639 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
5640 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
5642 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
5643 bm.bmType = 0;
5644 bm.bmWidth = bi->biWidth;
5645 bm.bmHeight = effHeight;
5646 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
5647 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
5648 bm.bmPlanes = bi->biPlanes;
5649 bm.bmBitsPixel = bi->biBitCount;
5650 bm.bmBits = NULL;
5652 /* Get storage location for DIB bits. Only use biSizeImage if it's valid and
5653 we're dealing with a compressed bitmap. Otherwise, use width * height. */
5654 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
5655 ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
5657 if (section)
5659 SYSTEM_INFO SystemInfo;
5660 DWORD mapOffset;
5661 INT mapSize;
5663 GetSystemInfo( &SystemInfo );
5664 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
5665 mapSize = totalSize + (offset - mapOffset);
5666 mapBits = MapViewOfFile( section,
5667 FILE_MAP_ALL_ACCESS,
5669 mapOffset,
5670 mapSize );
5671 bm.bmBits = (char *)mapBits + (offset - mapOffset);
5673 else if (ovr_pitch && offset)
5674 bm.bmBits = (LPVOID) offset;
5675 else {
5676 offset = 0;
5677 bm.bmBits = VirtualAlloc(NULL, totalSize,
5678 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
5681 /* Create Color Map */
5682 if (bm.bmBits && bm.bmBitsPixel <= 8)
5683 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? dc : NULL,
5684 usage, bm.bmBitsPixel, bmi, &nColorMap );
5686 /* Allocate Memory for DIB and fill structure */
5687 if (bm.bmBits)
5688 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
5689 if (dib)
5691 dib->dibSection.dsBm = bm;
5692 dib->dibSection.dsBmih = *bi;
5693 dib->dibSection.dsBmih.biSizeImage = totalSize;
5695 /* Set dsBitfields values */
5696 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
5698 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
5700 else switch( bi->biBitCount )
5702 case 15:
5703 case 16:
5704 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
5705 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
5706 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
5707 break;
5709 case 24:
5710 case 32:
5711 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff0000;
5712 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
5713 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
5714 break;
5716 dib->dibSection.dshSection = section;
5717 dib->dibSection.dsOffset = offset;
5719 dib->status = DIB_Status_None;
5720 dib->nColorMap = nColorMap;
5721 dib->colorMap = colorMap;
5724 /* Create Device Dependent Bitmap and add DIB pointer */
5725 if (dib)
5727 res = CreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage);
5728 if (res)
5730 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
5731 if (bmp)
5733 bmp->dib = (DIBSECTION *) dib;
5734 /* HACK for now */
5735 if(!bmp->physBitmap)
5736 X11DRV_CreateBitmap(res);
5741 /* Create XImage */
5742 if (dib && bmp)
5744 #ifdef HAVE_LIBXXSHM
5745 if (TSXShmQueryExtension(gdi_display) &&
5746 (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
5747 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
5749 ; /* Created Image */
5750 } else {
5751 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5752 dib->shminfo.shmid = -1;
5754 #else
5755 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5756 #endif
5759 /* Clean up in case of errors */
5760 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
5762 TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
5763 res, bmp, dib, bm.bmBits);
5764 if (bm.bmBits)
5766 if (section)
5767 UnmapViewOfFile(mapBits), bm.bmBits = NULL;
5768 else if (!offset)
5769 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
5772 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
5773 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
5774 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
5775 if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
5776 if (res) { DeleteObject(res); res = 0; }
5778 else if (bm.bmBits)
5780 /* Install fault handler, if possible */
5781 InitializeCriticalSection(&(dib->lock));
5782 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
5784 if (section || offset)
5786 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5787 if (dib) dib->status = DIB_Status_AppMod;
5789 else
5791 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5792 if (dib) dib->status = DIB_Status_InSync;
5797 /* Return BITMAP handle and storage location */
5798 if (bmp) GDI_ReleaseObj(res);
5799 if (bm.bmBits && bits) *bits = bm.bmBits;
5800 return res;
5803 /***********************************************************************
5804 * X11DRV_DIB_DeleteDIBSection
5806 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
5808 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5810 if (dib->image)
5812 #ifdef HAVE_LIBXXSHM
5813 if (dib->shminfo.shmid != -1)
5815 TSXShmDetach (gdi_display, &(dib->shminfo));
5816 XDestroyImage (dib->image);
5817 shmdt (dib->shminfo.shmaddr);
5818 dib->shminfo.shmid = -1;
5820 else
5821 #endif
5822 XDestroyImage( dib->image );
5825 if (dib->colorMap)
5826 HeapFree(GetProcessHeap(), 0, dib->colorMap);
5828 DeleteCriticalSection(&(dib->lock));
5831 /***********************************************************************
5832 * X11DRV_DIB_SetDIBColorTable
5834 UINT X11DRV_DIB_SetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT count, const RGBQUAD *colors)
5836 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5838 if (dib && dib->colorMap) {
5839 UINT end = count + start;
5840 if (end > dib->nColorMap) end = dib->nColorMap;
5842 * Changing color table might change the mapping between
5843 * DIB colors and X11 colors and thus alter the visible state
5844 * of the bitmap object.
5846 X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
5847 X11DRV_DIB_GenColorMap( dc, dib->colorMap, DIB_RGB_COLORS,
5848 dib->dibSection.dsBm.bmBitsPixel,
5849 TRUE, colors, start, end );
5850 X11DRV_DIB_Unlock(bmp, TRUE);
5851 return end - start;
5853 return 0;
5856 /***********************************************************************
5857 * X11DRV_DIB_GetDIBColorTable
5859 UINT X11DRV_DIB_GetDIBColorTable(BITMAPOBJ *bmp, DC *dc, UINT start, UINT count, RGBQUAD *colors)
5861 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5863 if (dib && dib->colorMap) {
5864 UINT i, end = count + start;
5865 if (end > dib->nColorMap) end = dib->nColorMap;
5866 for (i = start; i < end; i++,colors++) {
5867 COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
5868 colors->rgbBlue = GetBValue(col);
5869 colors->rgbGreen = GetGValue(col);
5870 colors->rgbRed = GetRValue(col);
5871 colors->rgbReserved = 0;
5873 return end-start;
5875 return 0;
5879 /**************************************************************************
5880 * X11DRV_DIB_CreateDIBFromPixmap
5882 * Allocates a packed DIB and copies the Pixmap data into it.
5883 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
5885 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
5887 HBITMAP hBmp = 0;
5888 BITMAPOBJ *pBmp = NULL;
5889 HGLOBAL hPackedDIB = 0;
5891 /* Allocates an HBITMAP which references the Pixmap passed to us */
5892 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
5893 if (!hBmp)
5895 TRACE("\tCould not create bitmap header for Pixmap\n");
5896 goto END;
5900 * Create a packed DIB from the Pixmap wrapper bitmap created above.
5901 * A packed DIB contains a BITMAPINFO structure followed immediately by
5902 * an optional color palette and the pixel data.
5904 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
5906 /* Get a pointer to the BITMAPOBJ structure */
5907 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5909 /* We can now get rid of the HBITMAP wrapper we created earlier.
5910 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
5912 if (!bDeletePixmap)
5914 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
5915 pBmp->physBitmap = NULL;
5916 pBmp->funcs = NULL;
5918 GDI_ReleaseObj( hBmp );
5919 DeleteObject(hBmp);
5921 END:
5922 TRACE("\tReturning packed DIB %x\n", hPackedDIB);
5923 return hPackedDIB;
5927 /**************************************************************************
5928 * X11DRV_DIB_CreatePixmapFromDIB
5930 * Creates a Pixmap from a packed DIB
5932 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
5934 Pixmap pixmap = None;
5935 HBITMAP hBmp = 0;
5936 BITMAPOBJ *pBmp = NULL;
5937 LPBYTE pPackedDIB = NULL;
5938 LPBITMAPINFO pbmi = NULL;
5939 LPBITMAPINFOHEADER pbmiHeader = NULL;
5940 LPBYTE pbits = NULL;
5942 /* Get a pointer to the packed DIB's data */
5943 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
5944 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
5945 pbmi = (LPBITMAPINFO)pPackedDIB;
5946 pbits = (LPBYTE)(pPackedDIB
5947 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
5949 /* Create a DDB from the DIB */
5951 hBmp = CreateDIBitmap(hdc,
5952 pbmiHeader,
5953 CBM_INIT,
5954 (LPVOID)pbits,
5955 pbmi,
5956 DIB_RGB_COLORS);
5958 GlobalUnlock(hPackedDIB);
5960 TRACE("CreateDIBitmap returned %x\n", hBmp);
5962 /* Retrieve the internal Pixmap from the DDB */
5964 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5966 pixmap = (Pixmap)pBmp->physBitmap;
5967 /* clear the physBitmap so that we can steal its pixmap */
5968 pBmp->physBitmap = NULL;
5969 pBmp->funcs = NULL;
5971 /* Delete the DDB we created earlier now that we have stolen its pixmap */
5972 GDI_ReleaseObj( hBmp );
5973 DeleteObject(hBmp);
5975 TRACE("\tReturning Pixmap %ld\n", pixmap);
5976 return pixmap;