Move caret when selecting a text area with the mouse.
[wine/multimedia.git] / graphics / x11drv / dib.c
blobbd437675bbb95bb2d9d9ec27a0e1daa3c75be0c0
1 /*
2 * X11DRV device-independent bitmaps
4 * Copyright 1993,1994 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include "ts_xlib.h"
24 #include "ts_xutil.h"
25 #ifdef HAVE_LIBXXSHM
26 # include "ts_xshm.h"
27 # ifdef HAVE_SYS_SHM_H
28 # include <sys/shm.h>
29 # endif
30 # ifdef HAVE_SYS_IPC_H
31 # include <sys/ipc.h>
32 # endif
33 #endif /* defined(HAVE_LIBXXSHM) */
35 #include <stdlib.h>
36 #include <string.h>
37 #include "windef.h"
38 #include "bitmap.h"
39 #include "x11drv.h"
40 #include "wine/debug.h"
41 #include "gdi.h"
42 #include "palette.h"
43 #include "global.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
46 WINE_DECLARE_DEBUG_CHANNEL(x11drv);
48 static int ximageDepthTable[32];
50 /* This structure holds the arguments for DIB_SetImageBits() */
51 typedef struct
53 X11DRV_PDEVICE *physDev;
54 LPCVOID bits;
55 XImage *image;
56 PALETTEENTRY *palentry;
57 int lines;
58 DWORD infoWidth;
59 WORD depth;
60 WORD infoBpp;
61 WORD compression;
62 RGBQUAD *colorMap;
63 int nColorMap;
64 Drawable drawable;
65 GC gc;
66 int xSrc;
67 int ySrc;
68 int xDest;
69 int yDest;
70 int width;
71 int height;
72 DWORD rMask;
73 DWORD gMask;
74 DWORD bMask;
75 BOOL useShm;
76 int dibpitch;
77 } X11DRV_DIB_IMAGEBITS_DESCR;
80 enum Rle_EscapeCodes
82 RLE_EOL = 0, /* End of line */
83 RLE_END = 1, /* End of bitmap */
84 RLE_DELTA = 2 /* Delta */
87 /***********************************************************************
88 * X11DRV_DIB_GetXImageWidthBytes
90 * Return the width of an X image in bytes
92 inline static int X11DRV_DIB_GetXImageWidthBytes( int width, int depth )
94 if (!depth || depth > 32) goto error;
96 if (!ximageDepthTable[depth-1])
98 XImage *testimage = XCreateImage( gdi_display, visual, depth,
99 ZPixmap, 0, NULL, 1, 1, 32, 20 );
100 if (testimage)
102 ximageDepthTable[depth-1] = testimage->bits_per_pixel;
103 XDestroyImage( testimage );
105 else ximageDepthTable[depth-1] = -1;
107 if (ximageDepthTable[depth-1] != -1)
108 return (4 * ((width * ximageDepthTable[depth-1] + 31) / 32));
110 error:
111 WARN( "(%d): Unsupported depth\n", depth );
112 return 4 * width;
116 /***********************************************************************
117 * X11DRV_DIB_CreateXImage
119 * Create an X image.
121 XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth )
123 int width_bytes;
124 XImage *image;
126 wine_tsx11_lock();
127 width_bytes = X11DRV_DIB_GetXImageWidthBytes( width, depth );
128 image = XCreateImage( gdi_display, visual, depth, ZPixmap, 0,
129 calloc( height, width_bytes ),
130 width, height, 32, width_bytes );
131 wine_tsx11_unlock();
132 return image;
136 /***********************************************************************
137 * X11DRV_DIB_GenColorMap
139 * Fills the color map of a bitmap palette. Should not be called
140 * for a >8-bit deep bitmap.
142 int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
143 WORD coloruse, WORD depth, BOOL quads,
144 const void *colorPtr, int start, int end )
146 int i;
148 if (coloruse == DIB_RGB_COLORS)
150 int max = 1 << depth;
152 if (end > max) end = max;
154 if (quads)
156 RGBQUAD * rgb = (RGBQUAD *)colorPtr;
158 if (depth == 1) /* Monochrome */
159 for (i = start; i < end; i++, rgb++)
160 colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
161 rgb->rgbBlue > 255*3/2);
162 else
163 for (i = start; i < end; i++, rgb++)
164 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbRed,
165 rgb->rgbGreen,
166 rgb->rgbBlue));
168 else
170 RGBTRIPLE * rgb = (RGBTRIPLE *)colorPtr;
172 if (depth == 1) /* Monochrome */
173 for (i = start; i < end; i++, rgb++)
174 colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
175 rgb->rgbtBlue > 255*3/2);
176 else
177 for (i = start; i < end; i++, rgb++)
178 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbtRed,
179 rgb->rgbtGreen,
180 rgb->rgbtBlue));
183 else /* DIB_PAL_COLORS */
185 if (colorPtr) {
186 WORD * index = (WORD *)colorPtr;
188 for (i = start; i < end; i++, index++)
189 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(*index) );
190 } else {
191 for (i = start; i < end; i++)
192 colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, PALETTEINDEX(i) );
196 return colorMapping;
199 /***********************************************************************
200 * X11DRV_DIB_BuildColorMap
202 * Build the color map from the bitmap palette. Should not be called
203 * for a >8-bit deep bitmap.
205 int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
206 const BITMAPINFO *info, int *nColors )
208 int colors;
209 BOOL isInfo;
210 const void *colorPtr;
211 int *colorMapping;
213 if ((isInfo = (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))))
215 colors = info->bmiHeader.biClrUsed;
216 if (!colors) colors = 1 << info->bmiHeader.biBitCount;
217 colorPtr = info->bmiColors;
219 else /* assume BITMAPCOREINFO */
221 colors = 1 << ((BITMAPCOREHEADER *)&info->bmiHeader)->bcBitCount;
222 colorPtr = (WORD *)((BITMAPCOREINFO *)info)->bmciColors;
225 if (colors > 256)
227 ERR("called with >256 colors!\n");
228 return NULL;
231 /* just so CopyDIBSection doesn't have to create an identity palette */
232 if (coloruse == (WORD)-1) colorPtr = NULL;
234 if (!(colorMapping = (int *)HeapAlloc(GetProcessHeap(), 0,
235 colors * sizeof(int) )))
236 return NULL;
238 *nColors = colors;
239 return X11DRV_DIB_GenColorMap( physDev, colorMapping, coloruse, depth,
240 isInfo, colorPtr, 0, colors);
244 /***********************************************************************
245 * X11DRV_DIB_MapColor
247 int X11DRV_DIB_MapColor( int *physMap, int nPhysMap, int phys, int oldcol )
249 int color;
251 if ((oldcol < nPhysMap) && (physMap[oldcol] == phys))
252 return oldcol;
254 for (color = 0; color < nPhysMap; color++)
255 if (physMap[color] == phys)
256 return color;
258 WARN("Strange color %08x\n", phys);
259 return 0;
263 /*********************************************************************
264 * X11DRV_DIB_GetNearestIndex
266 * Helper for X11DRV_DIB_GetDIBits.
267 * Returns the nearest colour table index for a given RGB.
268 * Nearest is defined by minimizing the sum of the squares.
270 static INT X11DRV_DIB_GetNearestIndex(RGBQUAD *colormap, int numColors, BYTE r, BYTE g, BYTE b)
272 INT i, best = -1, diff, bestdiff = -1;
273 RGBQUAD *color;
275 for(color = colormap, i = 0; i < numColors; color++, i++) {
276 diff = (r - color->rgbRed) * (r - color->rgbRed) +
277 (g - color->rgbGreen) * (g - color->rgbGreen) +
278 (b - color->rgbBlue) * (b - color->rgbBlue);
279 if(diff == 0)
280 return i;
281 if(best == -1 || diff < bestdiff) {
282 best = i;
283 bestdiff = diff;
286 return best;
288 /*********************************************************************
289 * X11DRV_DIB_MaskToShift
291 * Helper for X11DRV_DIB_GetDIBits.
292 * Returns the by how many bits to shift a given color so that it is
293 * in the proper position.
295 static INT X11DRV_DIB_MaskToShift(DWORD mask)
297 int shift;
299 if (mask==0)
300 return 0;
302 shift=0;
303 while ((mask&1)==0) {
304 mask>>=1;
305 shift++;
307 return shift;
310 /***********************************************************************
311 * X11DRV_DIB_Convert_any_asis
313 * All X11DRV_DIB_Convert_Xxx functions take at least the following
314 * parameters:
315 * - width
316 * This is the width in pixel of the surface to copy. This may be less
317 * than the full width of the image.
318 * - height
319 * The number of lines to copy. This may be less than the full height
320 * of the image. This is always >0.
321 * - srcbits
322 * Points to the first byte containing data to be copied. If the source
323 * surface starts are coordinates (x,y) then this is:
324 * image_ptr+x*bytes_pre_pixel+y*bytes_per_line
325 * (with further adjustments for top-down/bottom-up images)
326 * - srclinebytes
327 * This is the number of bytes per line. It may be >0 or <0 depending on
328 * whether this is a top-down or bottom-up image.
329 * - dstbits
330 * Same as srcbits but for the destination
331 * - dstlinebytes
332 * Same as srclinebytes but for the destination.
334 * Notes:
335 * - The supported Dib formats are: pal1, pal4, pal8, rgb555, bgr555,
336 * rgb565, bgr565, rgb888 and any 32bit (0888) format.
337 * The supported XImage (Bmp) formats are: pal1, pal4, pal8,
338 * rgb555, bgr555, rgb565, bgr565, rgb888, bgr888, rgb0888, bgr0888.
339 * - Rgb formats are those for which the masks are such that:
340 * red_mask > green_mask > blue_mask
341 * - Bgr formats are those for which the masks sort in the other direction.
342 * - Many conversion functions handle both rgb->bgr and bgr->rgb conversions
343 * so the comments use h, g, l to mean respectively the source color in the
344 * high bits, the green, and the source color in the low bits.
346 static void X11DRV_DIB_Convert_any_asis(int width, int height,
347 int bytes_per_pixel,
348 const void* srcbits, int srclinebytes,
349 void* dstbits, int dstlinebytes)
351 int y;
353 width*=bytes_per_pixel;
354 for (y=0; y<height; y++) {
355 memcpy(dstbits, srcbits, width);
356 srcbits = (char*)srcbits + srclinebytes;
357 dstbits = (char*)dstbits + dstlinebytes;
362 * 15 bit conversions
365 static void X11DRV_DIB_Convert_555_reverse(int width, int height,
366 const void* srcbits, int srclinebytes,
367 void* dstbits, int dstlinebytes)
369 const DWORD* srcpixel;
370 DWORD* dstpixel;
371 int x,y;
373 for (y=0; y<height; y++) {
374 srcpixel=srcbits;
375 dstpixel=dstbits;
376 for (x=0; x<width/2; x++) {
377 /* Do 2 pixels at a time */
378 DWORD srcval;
379 srcval=*srcpixel++;
380 *dstpixel++=((srcval << 10) & 0x7c007c00) | /* h */
381 ( srcval & 0x03e003e0) | /* g */
382 ((srcval >> 10) & 0x001f001f); /* l */
384 if (width&1) {
385 /* And the the odd pixel */
386 WORD srcval;
387 srcval=*((WORD*)srcpixel);
388 *((WORD*)dstpixel)=((srcval << 10) & 0x7c00) | /* h */
389 ( srcval & 0x03e0) | /* g */
390 ((srcval >> 10) & 0x001f); /* l */
392 srcbits = (char*)srcbits + srclinebytes;
393 dstbits = (char*)dstbits + dstlinebytes;
397 static void X11DRV_DIB_Convert_555_to_565_asis(int width, int height,
398 const void* srcbits, int srclinebytes,
399 void* dstbits, int dstlinebytes)
401 const DWORD* srcpixel;
402 DWORD* dstpixel;
403 int x,y;
405 for (y=0; y<height; y++) {
406 srcpixel=srcbits;
407 dstpixel=dstbits;
408 for (x=0; x<width/2; x++) {
409 /* Do 2 pixels at a time */
410 DWORD srcval;
411 srcval=*srcpixel++;
412 *dstpixel++=((srcval << 1) & 0xffc0ffc0) | /* h, g */
413 ((srcval >> 4) & 0x00200020) | /* g - 1 bit */
414 ( srcval & 0x001f001f); /* l */
416 if (width&1) {
417 /* And the the odd pixel */
418 WORD srcval;
419 srcval=*((WORD*)srcpixel);
420 *((WORD*)dstpixel)=((srcval << 1) & 0xffc0) | /* h, g */
421 ((srcval >> 4) & 0x0020) | /* g - 1 bit */
422 (srcval & 0x001f); /* l */
424 srcbits = (char*)srcbits + srclinebytes;
425 dstbits = (char*)dstbits + dstlinebytes;
429 static void X11DRV_DIB_Convert_555_to_565_reverse(int width, int height,
430 const void* srcbits, int srclinebytes,
431 void* dstbits, int dstlinebytes)
433 const DWORD* srcpixel;
434 DWORD* dstpixel;
435 int x,y;
437 for (y=0; y<height; y++) {
438 srcpixel=srcbits;
439 dstpixel=dstbits;
440 for (x=0; x<width/2; x++) {
441 /* Do 2 pixels at a time */
442 DWORD srcval;
443 srcval=*srcpixel++;
444 *dstpixel++=((srcval >> 10) & 0x001f001f) | /* h */
445 ((srcval << 1) & 0x07c007c0) | /* g */
446 ((srcval >> 4) & 0x00200020) | /* g - 1 bit */
447 ((srcval << 11) & 0xf800f800); /* l */
449 if (width&1) {
450 /* And the the odd pixel */
451 WORD srcval;
452 srcval=*((WORD*)srcpixel);
453 *((WORD*)dstpixel)=((srcval >> 10) & 0x001f) | /* h */
454 ((srcval << 1) & 0x07c0) | /* g */
455 ((srcval >> 4) & 0x0020) | /* g - 1 bit */
456 ((srcval << 11) & 0xf800); /* l */
458 srcbits = (char*)srcbits + srclinebytes;
459 dstbits = (char*)dstbits + dstlinebytes;
463 static void X11DRV_DIB_Convert_555_to_888_asis(int width, int height,
464 const void* srcbits, int srclinebytes,
465 void* dstbits, int dstlinebytes)
467 const WORD* srcpixel;
468 BYTE* dstpixel;
469 int x,y;
471 for (y=0; y<height; y++) {
472 srcpixel=srcbits;
473 dstpixel=dstbits;
474 for (x=0; x<width; x++) {
475 WORD srcval;
476 srcval=*srcpixel++;
477 dstpixel[0]=((srcval << 3) & 0xf8) | /* l */
478 ((srcval >> 2) & 0x07); /* l - 3 bits */
479 dstpixel[1]=((srcval >> 2) & 0xf8) | /* g */
480 ((srcval >> 7) & 0x07); /* g - 3 bits */
481 dstpixel[2]=((srcval >> 7) & 0xf8) | /* h */
482 ((srcval >> 12) & 0x07); /* h - 3 bits */
483 dstpixel+=3;
485 srcbits = (char*)srcbits + srclinebytes;
486 dstbits = (char*)dstbits + dstlinebytes;
490 static void X11DRV_DIB_Convert_555_to_888_reverse(int width, int height,
491 const void* srcbits, int srclinebytes,
492 void* dstbits, int dstlinebytes)
494 const WORD* srcpixel;
495 BYTE* dstpixel;
496 int x,y;
498 for (y=0; y<height; y++) {
499 srcpixel=srcbits;
500 dstpixel=dstbits;
501 for (x=0; x<width; x++) {
502 WORD srcval;
503 srcval=*srcpixel++;
504 dstpixel[0]=((srcval >> 7) & 0xf8) | /* h */
505 ((srcval >> 12) & 0x07); /* h - 3 bits */
506 dstpixel[1]=((srcval >> 2) & 0xf8) | /* g */
507 ((srcval >> 7) & 0x07); /* g - 3 bits */
508 dstpixel[2]=((srcval << 3) & 0xf8) | /* l */
509 ((srcval >> 2) & 0x07); /* l - 3 bits */
510 dstpixel+=3;
512 srcbits = (char*)srcbits + srclinebytes;
513 dstbits = (char*)dstbits + dstlinebytes;
517 static void X11DRV_DIB_Convert_555_to_0888_asis(int width, int height,
518 const void* srcbits, int srclinebytes,
519 void* dstbits, int dstlinebytes)
521 const WORD* srcpixel;
522 DWORD* dstpixel;
523 int x,y;
525 for (y=0; y<height; y++) {
526 srcpixel=srcbits;
527 dstpixel=dstbits;
528 for (x=0; x<width; x++) {
529 WORD srcval;
530 srcval=*srcpixel++;
531 *dstpixel++=((srcval << 9) & 0xf80000) | /* h */
532 ((srcval << 4) & 0x070000) | /* h - 3 bits */
533 ((srcval << 6) & 0x00f800) | /* g */
534 ((srcval << 1) & 0x000700) | /* g - 3 bits */
535 ((srcval << 3) & 0x0000f8) | /* l */
536 ((srcval >> 2) & 0x000007); /* l - 3 bits */
538 srcbits = (char*)srcbits + srclinebytes;
539 dstbits = (char*)dstbits + dstlinebytes;
543 static void X11DRV_DIB_Convert_555_to_0888_reverse(int width, int height,
544 const void* srcbits, int srclinebytes,
545 void* dstbits, int dstlinebytes)
547 const WORD* srcpixel;
548 DWORD* dstpixel;
549 int x,y;
551 for (y=0; y<height; y++) {
552 srcpixel=srcbits;
553 dstpixel=dstbits;
554 for (x=0; x<width; x++) {
555 WORD srcval;
556 srcval=*srcpixel++;
557 *dstpixel++=((srcval >> 7) & 0x0000f8) | /* h */
558 ((srcval >> 12) & 0x000007) | /* h - 3 bits */
559 ((srcval << 6) & 0x00f800) | /* g */
560 ((srcval << 1) & 0x000700) | /* g - 3 bits */
561 ((srcval << 19) & 0xf80000) | /* l */
562 ((srcval << 14) & 0x070000); /* l - 3 bits */
564 srcbits = (char*)srcbits + srclinebytes;
565 dstbits = (char*)dstbits + dstlinebytes;
569 static void X11DRV_DIB_Convert_5x5_to_any0888(int width, int height,
570 const void* srcbits, int srclinebytes,
571 WORD rsrc, WORD gsrc, WORD bsrc,
572 void* dstbits, int dstlinebytes,
573 DWORD rdst, DWORD gdst, DWORD bdst)
575 int rRightShift1,gRightShift1,bRightShift1;
576 int rRightShift2,gRightShift2,bRightShift2;
577 BYTE gMask1,gMask2;
578 int rLeftShift,gLeftShift,bLeftShift;
579 const WORD* srcpixel;
580 DWORD* dstpixel;
581 int x,y;
583 /* Note, the source pixel value is shifted left by 16 bits so that
584 * we know we will always have to shift right to extract the components.
586 rRightShift1=16+X11DRV_DIB_MaskToShift(rsrc)-3;
587 gRightShift1=16+X11DRV_DIB_MaskToShift(gsrc)-3;
588 bRightShift1=16+X11DRV_DIB_MaskToShift(bsrc)-3;
589 rRightShift2=rRightShift1+5;
590 gRightShift2=gRightShift1+5;
591 bRightShift2=bRightShift1+5;
592 if (gsrc==0x03e0) {
593 /* Green has 5 bits, like the others */
594 gMask1=0xf8;
595 gMask2=0x07;
596 } else {
597 /* Green has 6 bits, not 5. Compensate. */
598 gRightShift1++;
599 gRightShift2+=2;
600 gMask1=0xfc;
601 gMask2=0x03;
604 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
605 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
606 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
608 for (y=0; y<height; y++) {
609 srcpixel=srcbits;
610 dstpixel=dstbits;
611 for (x=0; x<width; x++) {
612 DWORD srcval;
613 BYTE red,green,blue;
614 srcval=*srcpixel++ << 16;
615 red= ((srcval >> rRightShift1) & 0xf8) |
616 ((srcval >> rRightShift2) & 0x07);
617 green=((srcval >> gRightShift1) & gMask1) |
618 ((srcval >> gRightShift2) & gMask2);
619 blue= ((srcval >> bRightShift1) & 0xf8) |
620 ((srcval >> bRightShift2) & 0x07);
621 *dstpixel++=(red << rLeftShift) |
622 (green << gLeftShift) |
623 (blue << bLeftShift);
625 srcbits = (char*)srcbits + srclinebytes;
626 dstbits = (char*)dstbits + dstlinebytes;
631 * 16 bits conversions
634 static void X11DRV_DIB_Convert_565_reverse(int width, int height,
635 const void* srcbits, int srclinebytes,
636 void* dstbits, int dstlinebytes)
638 const DWORD* srcpixel;
639 DWORD* dstpixel;
640 int x,y;
642 for (y=0; y<height; y++) {
643 srcpixel=srcbits;
644 dstpixel=dstbits;
645 for (x=0; x<width/2; x++) {
646 /* Do 2 pixels at a time */
647 DWORD srcval;
648 srcval=*srcpixel++;
649 *dstpixel++=((srcval << 11) & 0xf800f800) | /* h */
650 ( srcval & 0x07e007e0) | /* g */
651 ((srcval >> 11) & 0x001f001f); /* l */
653 if (width&1) {
654 /* And the the odd pixel */
655 WORD srcval;
656 srcval=*((WORD*)srcpixel);
657 *((WORD*)dstpixel)=((srcval << 11) & 0xf800) | /* h */
658 ( srcval & 0x07e0) | /* g */
659 ((srcval >> 11) & 0x001f); /* l */
661 srcbits = (char*)srcbits + srclinebytes;
662 dstbits = (char*)dstbits + dstlinebytes;
666 static void X11DRV_DIB_Convert_565_to_555_asis(int width, int height,
667 const void* srcbits, int srclinebytes,
668 void* dstbits, int dstlinebytes)
670 const DWORD* srcpixel;
671 DWORD* dstpixel;
672 int x,y;
674 for (y=0; y<height; y++) {
675 srcpixel=srcbits;
676 dstpixel=dstbits;
677 for (x=0; x<width/2; x++) {
678 /* Do 2 pixels at a time */
679 DWORD srcval;
680 srcval=*srcpixel++;
681 *dstpixel++=((srcval >> 1) & 0x7fe07fe0) | /* h, g */
682 ( srcval & 0x001f001f); /* l */
684 if (width&1) {
685 /* And the the odd pixel */
686 WORD srcval;
687 srcval=*((WORD*)srcpixel);
688 *((WORD*)dstpixel)=((srcval >> 1) & 0x7fe0) | /* h, g */
689 ( srcval & 0x001f); /* l */
691 srcbits = (char*)srcbits + srclinebytes;
692 dstbits = (char*)dstbits + dstlinebytes;
696 static void X11DRV_DIB_Convert_565_to_555_reverse(int width, int height,
697 const void* srcbits, int srclinebytes,
698 void* dstbits, int dstlinebytes)
700 const DWORD* srcpixel;
701 DWORD* dstpixel;
702 int x,y;
704 for (y=0; y<height; y++) {
705 srcpixel=srcbits;
706 dstpixel=dstbits;
707 for (x=0; x<width/2; x++) {
708 /* Do 2 pixels at a time */
709 DWORD srcval;
710 srcval=*srcpixel++;
711 *dstpixel++=((srcval >> 11) & 0x001f001f) | /* h */
712 ((srcval >> 1) & 0x03e003e0) | /* g */
713 ((srcval << 10) & 0x7c007c00); /* l */
715 if (width&1) {
716 /* And the the odd pixel */
717 WORD srcval;
718 srcval=*((WORD*)srcpixel);
719 *((WORD*)dstpixel)=((srcval >> 11) & 0x001f) | /* h */
720 ((srcval >> 1) & 0x03e0) | /* g */
721 ((srcval << 10) & 0x7c00); /* l */
723 srcbits = (char*)srcbits + srclinebytes;
724 dstbits = (char*)dstbits + dstlinebytes;
728 static void X11DRV_DIB_Convert_565_to_888_asis(int width, int height,
729 const void* srcbits, int srclinebytes,
730 void* dstbits, int dstlinebytes)
732 const WORD* srcpixel;
733 BYTE* dstpixel;
734 int x,y;
736 for (y=0; y<height; y++) {
737 srcpixel=srcbits;
738 dstpixel=dstbits;
739 for (x=0; x<width; x++) {
740 WORD srcval;
741 srcval=*srcpixel++;
742 dstpixel[0]=((srcval << 3) & 0xf8) | /* l */
743 ((srcval >> 2) & 0x07); /* l - 3 bits */
744 dstpixel[1]=((srcval >> 3) & 0xfc) | /* g */
745 ((srcval >> 9) & 0x03); /* g - 2 bits */
746 dstpixel[2]=((srcval >> 8) & 0xf8) | /* h */
747 ((srcval >> 13) & 0x07); /* h - 3 bits */
748 dstpixel+=3;
750 srcbits = (char*)srcbits + srclinebytes;
751 dstbits = (char*)dstbits + dstlinebytes;
755 static void X11DRV_DIB_Convert_565_to_888_reverse(int width, int height,
756 const void* srcbits, int srclinebytes,
757 void* dstbits, int dstlinebytes)
759 const WORD* srcpixel;
760 BYTE* dstpixel;
761 int x,y;
763 for (y=0; y<height; y++) {
764 srcpixel=srcbits;
765 dstpixel=dstbits;
766 for (x=0; x<width; x++) {
767 WORD srcval;
768 srcval=*srcpixel++;
769 dstpixel[0]=((srcval >> 8) & 0xf8) | /* h */
770 ((srcval >> 13) & 0x07); /* h - 3 bits */
771 dstpixel[1]=((srcval >> 3) & 0xfc) | /* g */
772 ((srcval >> 9) & 0x03); /* g - 2 bits */
773 dstpixel[2]=((srcval << 3) & 0xf8) | /* l */
774 ((srcval >> 2) & 0x07); /* l - 3 bits */
775 dstpixel+=3;
777 srcbits = (char*)srcbits + srclinebytes;
778 dstbits = (char*)dstbits + dstlinebytes;
782 static void X11DRV_DIB_Convert_565_to_0888_asis(int width, int height,
783 const void* srcbits, int srclinebytes,
784 void* dstbits, int dstlinebytes)
786 const WORD* srcpixel;
787 DWORD* dstpixel;
788 int x,y;
790 for (y=0; y<height; y++) {
791 srcpixel=srcbits;
792 dstpixel=dstbits;
793 for (x=0; x<width; x++) {
794 WORD srcval;
795 srcval=*srcpixel++;
796 *dstpixel++=((srcval << 8) & 0xf80000) | /* h */
797 ((srcval << 3) & 0x070000) | /* h - 3 bits */
798 ((srcval << 5) & 0x00fc00) | /* g */
799 ((srcval >> 1) & 0x000300) | /* g - 2 bits */
800 ((srcval << 3) & 0x0000f8) | /* l */
801 ((srcval >> 2) & 0x000007); /* l - 3 bits */
803 srcbits = (char*)srcbits + srclinebytes;
804 dstbits = (char*)dstbits + dstlinebytes;
808 static void X11DRV_DIB_Convert_565_to_0888_reverse(int width, int height,
809 const void* srcbits, int srclinebytes,
810 void* dstbits, int dstlinebytes)
812 const WORD* srcpixel;
813 DWORD* dstpixel;
814 int x,y;
816 for (y=0; y<height; y++) {
817 srcpixel=srcbits;
818 dstpixel=dstbits;
819 for (x=0; x<width; x++) {
820 WORD srcval;
821 srcval=*srcpixel++;
822 *dstpixel++=((srcval >> 8) & 0x0000f8) | /* h */
823 ((srcval >> 13) & 0x000007) | /* h - 3 bits */
824 ((srcval << 5) & 0x00fc00) | /* g */
825 ((srcval >> 1) & 0x000300) | /* g - 2 bits */
826 ((srcval << 19) & 0xf80000) | /* l */
827 ((srcval << 14) & 0x070000); /* l - 3 bits */
829 srcbits = (char*)srcbits + srclinebytes;
830 dstbits = (char*)dstbits + dstlinebytes;
835 * 24 bit conversions
838 static void X11DRV_DIB_Convert_888_reverse(int width, int height,
839 const void* srcbits, int srclinebytes,
840 void* dstbits, int dstlinebytes)
842 const BYTE* srcpixel;
843 BYTE* dstpixel;
844 int x,y;
846 for (y=0; y<height; y++) {
847 srcpixel=srcbits;
848 dstpixel=dstbits;
849 for (x=0; x<width; x++) {
850 dstpixel[0]=srcpixel[2];
851 dstpixel[1]=srcpixel[1];
852 dstpixel[2]=srcpixel[0];
853 srcpixel+=3;
854 dstpixel+=3;
856 srcbits = (char*)srcbits + srclinebytes;
857 dstbits = (char*)dstbits + dstlinebytes;
861 static void X11DRV_DIB_Convert_888_to_555_asis(int width, int height,
862 const void* srcbits, int srclinebytes,
863 void* dstbits, int dstlinebytes)
865 const DWORD* srcpixel;
866 const BYTE* srcbyte;
867 WORD* dstpixel;
868 int x,y;
869 int oddwidth;
871 oddwidth=width & 3;
872 width=width/4;
873 for (y=0; y<height; y++) {
874 srcpixel=srcbits;
875 dstpixel=dstbits;
876 for (x=0; x<width; x++) {
877 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
878 DWORD srcval1,srcval2;
879 srcval1=srcpixel[0];
880 dstpixel[0]=((srcval1 >> 3) & 0x001f) | /* l1 */
881 ((srcval1 >> 6) & 0x03e0) | /* g1 */
882 ((srcval1 >> 9) & 0x7c00); /* h1 */
883 srcval2=srcpixel[1];
884 dstpixel[1]=((srcval1 >> 27) & 0x001f) | /* l2 */
885 ((srcval2 << 2) & 0x03e0) | /* g2 */
886 ((srcval2 >> 1) & 0x7c00); /* h2 */
887 srcval1=srcpixel[2];
888 dstpixel[2]=((srcval2 >> 19) & 0x001f) | /* l3 */
889 ((srcval2 >> 22) & 0x03e0) | /* g3 */
890 ((srcval1 << 7) & 0x7c00); /* h3 */
891 dstpixel[3]=((srcval1 >> 11) & 0x001f) | /* l4 */
892 ((srcval1 >> 14) & 0x03e0) | /* g4 */
893 ((srcval1 >> 17) & 0x7c00); /* h4 */
894 srcpixel+=3;
895 dstpixel+=4;
897 /* And now up to 3 odd pixels */
898 srcbyte=(LPBYTE)srcpixel;
899 for (x=0; x<oddwidth; x++) {
900 WORD dstval;
901 dstval =((srcbyte[0] >> 3) & 0x001f); /* l */
902 dstval|=((srcbyte[1] << 2) & 0x03e0); /* g */
903 dstval|=((srcbyte[2] << 7) & 0x7c00); /* h */
904 *dstpixel++=dstval;
905 srcbyte+=3;
907 srcbits = (char*)srcbits + srclinebytes;
908 dstbits = (char*)dstbits + dstlinebytes;
912 static void X11DRV_DIB_Convert_888_to_555_reverse(int width, int height,
913 const void* srcbits, int srclinebytes,
914 void* dstbits, int dstlinebytes)
916 const DWORD* srcpixel;
917 const BYTE* srcbyte;
918 WORD* dstpixel;
919 int x,y;
920 int oddwidth;
922 oddwidth=width & 3;
923 width=width/4;
924 for (y=0; y<height; y++) {
925 srcpixel=srcbits;
926 dstpixel=dstbits;
927 for (x=0; x<width; x++) {
928 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
929 DWORD srcval1,srcval2;
930 srcval1=srcpixel[0];
931 dstpixel[0]=((srcval1 << 7) & 0x7c00) | /* l1 */
932 ((srcval1 >> 6) & 0x03e0) | /* g1 */
933 ((srcval1 >> 19) & 0x001f); /* h1 */
934 srcval2=srcpixel[1];
935 dstpixel[1]=((srcval1 >> 17) & 0x7c00) | /* l2 */
936 ((srcval2 << 2) & 0x03e0) | /* g2 */
937 ((srcval2 >> 11) & 0x001f); /* h2 */
938 srcval1=srcpixel[2];
939 dstpixel[2]=((srcval2 >> 9) & 0x7c00) | /* l3 */
940 ((srcval2 >> 22) & 0x03e0) | /* g3 */
941 ((srcval1 >> 3) & 0x001f); /* h3 */
942 dstpixel[3]=((srcval1 >> 1) & 0x7c00) | /* l4 */
943 ((srcval1 >> 14) & 0x03e0) | /* g4 */
944 ((srcval1 >> 27) & 0x001f); /* h4 */
945 srcpixel+=3;
946 dstpixel+=4;
948 /* And now up to 3 odd pixels */
949 srcbyte=(LPBYTE)srcpixel;
950 for (x=0; x<oddwidth; x++) {
951 WORD dstval;
952 dstval =((srcbyte[0] << 7) & 0x7c00); /* l */
953 dstval|=((srcbyte[1] << 2) & 0x03e0); /* g */
954 dstval|=((srcbyte[2] >> 3) & 0x001f); /* h */
955 *dstpixel++=dstval;
956 srcbyte+=3;
958 srcbits = (char*)srcbits + srclinebytes;
959 dstbits = (char*)dstbits + dstlinebytes;
963 static void X11DRV_DIB_Convert_888_to_565_asis(int width, int height,
964 const void* srcbits, int srclinebytes,
965 void* dstbits, int dstlinebytes)
967 const DWORD* srcpixel;
968 const BYTE* srcbyte;
969 WORD* dstpixel;
970 int x,y;
971 int oddwidth;
973 oddwidth=width & 3;
974 width=width/4;
975 for (y=0; y<height; y++) {
976 srcpixel=srcbits;
977 dstpixel=dstbits;
978 for (x=0; x<width; x++) {
979 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
980 DWORD srcval1,srcval2;
981 srcval1=srcpixel[0];
982 dstpixel[0]=((srcval1 >> 3) & 0x001f) | /* l1 */
983 ((srcval1 >> 5) & 0x07e0) | /* g1 */
984 ((srcval1 >> 8) & 0xf800); /* h1 */
985 srcval2=srcpixel[1];
986 dstpixel[1]=((srcval1 >> 27) & 0x001f) | /* l2 */
987 ((srcval2 << 3) & 0x07e0) | /* g2 */
988 ( srcval2 & 0xf800); /* h2 */
989 srcval1=srcpixel[2];
990 dstpixel[2]=((srcval2 >> 19) & 0x001f) | /* l3 */
991 ((srcval2 >> 21) & 0x07e0) | /* g3 */
992 ((srcval1 << 8) & 0xf800); /* h3 */
993 dstpixel[3]=((srcval1 >> 11) & 0x001f) | /* l4 */
994 ((srcval1 >> 13) & 0x07e0) | /* g4 */
995 ((srcval1 >> 16) & 0xf800); /* h4 */
996 srcpixel+=3;
997 dstpixel+=4;
999 /* And now up to 3 odd pixels */
1000 srcbyte=(LPBYTE)srcpixel;
1001 for (x=0; x<oddwidth; x++) {
1002 WORD dstval;
1003 dstval =((srcbyte[0] >> 3) & 0x001f); /* l */
1004 dstval|=((srcbyte[1] << 3) & 0x07e0); /* g */
1005 dstval|=((srcbyte[2] << 8) & 0xf800); /* h */
1006 *dstpixel++=dstval;
1007 srcbyte+=3;
1009 srcbits = (char*)srcbits + srclinebytes;
1010 dstbits = (char*)dstbits + dstlinebytes;
1014 static void X11DRV_DIB_Convert_888_to_565_reverse(int width, int height,
1015 const void* srcbits, int srclinebytes,
1016 void* dstbits, int dstlinebytes)
1018 const DWORD* srcpixel;
1019 const BYTE* srcbyte;
1020 WORD* dstpixel;
1021 int x,y;
1022 int oddwidth;
1024 oddwidth=width & 3;
1025 width=width/4;
1026 for (y=0; y<height; y++) {
1027 srcpixel=srcbits;
1028 dstpixel=dstbits;
1029 for (x=0; x<width; x++) {
1030 /* Do 4 pixels at a time: 3 dwords in and 4 words out */
1031 DWORD srcval1,srcval2;
1032 srcval1=srcpixel[0];
1033 dstpixel[0]=((srcval1 << 8) & 0xf800) | /* l1 */
1034 ((srcval1 >> 5) & 0x07e0) | /* g1 */
1035 ((srcval1 >> 19) & 0x001f); /* h1 */
1036 srcval2=srcpixel[1];
1037 dstpixel[1]=((srcval1 >> 16) & 0xf800) | /* l2 */
1038 ((srcval2 << 3) & 0x07e0) | /* g2 */
1039 ((srcval2 >> 11) & 0x001f); /* h2 */
1040 srcval1=srcpixel[2];
1041 dstpixel[2]=((srcval2 >> 8) & 0xf800) | /* l3 */
1042 ((srcval2 >> 21) & 0x07e0) | /* g3 */
1043 ((srcval1 >> 3) & 0x001f); /* h3 */
1044 dstpixel[3]=(srcval1 & 0xf800) | /* l4 */
1045 ((srcval1 >> 13) & 0x07e0) | /* g4 */
1046 ((srcval1 >> 27) & 0x001f); /* h4 */
1047 srcpixel+=3;
1048 dstpixel+=4;
1050 /* And now up to 3 odd pixels */
1051 srcbyte=(LPBYTE)srcpixel;
1052 for (x=0; x<oddwidth; x++) {
1053 WORD dstval;
1054 dstval =((srcbyte[0] << 8) & 0xf800); /* l */
1055 dstval|=((srcbyte[1] << 3) & 0x07e0); /* g */
1056 dstval|=((srcbyte[2] >> 3) & 0x001f); /* h */
1057 *dstpixel++=dstval;
1058 srcbyte+=3;
1060 srcbits = (char*)srcbits + srclinebytes;
1061 dstbits = (char*)dstbits + dstlinebytes;
1065 static void X11DRV_DIB_Convert_888_to_0888_asis(int width, int height,
1066 const void* srcbits, int srclinebytes,
1067 void* dstbits, int dstlinebytes)
1069 const DWORD* srcpixel;
1070 DWORD* dstpixel;
1071 int x,y;
1072 int oddwidth;
1074 oddwidth=width & 3;
1075 width=width/4;
1076 for (y=0; y<height; y++) {
1077 srcpixel=srcbits;
1078 dstpixel=dstbits;
1079 for (x=0; x<width; x++) {
1080 /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
1081 DWORD srcval1,srcval2;
1082 srcval1=srcpixel[0];
1083 dstpixel[0]=( srcval1 & 0x00ffffff); /* h1, g1, l1 */
1084 srcval2=srcpixel[1];
1085 dstpixel[1]=( srcval1 >> 24) | /* l2 */
1086 ((srcval2 << 8) & 0x00ffff00); /* h2, g2 */
1087 srcval1=srcpixel[2];
1088 dstpixel[2]=( srcval2 >> 16) | /* g3, l3 */
1089 ((srcval1 << 16) & 0x00ff0000); /* h3 */
1090 dstpixel[3]=( srcval1 >> 8); /* h4, g4, l4 */
1091 srcpixel+=3;
1092 dstpixel+=4;
1094 /* And now up to 3 odd pixels */
1095 for (x=0; x<oddwidth; x++) {
1096 DWORD srcval;
1097 srcval=*srcpixel;
1098 srcpixel=(LPDWORD)(((char*)srcpixel)+3);
1099 *dstpixel++=( srcval & 0x00ffffff); /* h, g, l */
1101 srcbits = (char*)srcbits + srclinebytes;
1102 dstbits = (char*)dstbits + dstlinebytes;
1106 static void X11DRV_DIB_Convert_888_to_0888_reverse(int width, int height,
1107 const void* srcbits, int srclinebytes,
1108 void* dstbits, int dstlinebytes)
1110 const DWORD* srcpixel;
1111 DWORD* dstpixel;
1112 int x,y;
1113 int oddwidth;
1115 oddwidth=width & 3;
1116 width=width/4;
1117 for (y=0; y<height; y++) {
1118 srcpixel=srcbits;
1119 dstpixel=dstbits;
1120 for (x=0; x<width; x++) {
1121 /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
1122 DWORD srcval1,srcval2;
1124 srcval1=srcpixel[0];
1125 dstpixel[0]=((srcval1 >> 16) & 0x0000ff) | /* h1 */
1126 ( srcval1 & 0x00ff00) | /* g1 */
1127 ((srcval1 << 16) & 0xff0000); /* l1 */
1128 srcval2=srcpixel[1];
1129 dstpixel[1]=((srcval1 >> 8) & 0xff0000) | /* l2 */
1130 ((srcval2 << 8) & 0x00ff00) | /* g2 */
1131 ((srcval2 >> 8) & 0x0000ff); /* h2 */
1132 srcval1=srcpixel[2];
1133 dstpixel[2]=( srcval2 & 0xff0000) | /* l3 */
1134 ((srcval2 >> 16) & 0x00ff00) | /* g3 */
1135 ( srcval1 & 0x0000ff); /* h3 */
1136 dstpixel[3]=((srcval1 >> 24) & 0x0000ff) | /* h4 */
1137 ((srcval1 >> 8) & 0x00ff00) | /* g4 */
1138 ((srcval1 << 8) & 0xff0000); /* l4 */
1139 srcpixel+=3;
1140 dstpixel+=4;
1142 /* And now up to 3 odd pixels */
1143 for (x=0; x<oddwidth; x++) {
1144 DWORD srcval;
1145 srcval=*srcpixel;
1146 srcpixel=(LPDWORD)(((char*)srcpixel)+3);
1147 *dstpixel++=((srcval >> 16) & 0x0000ff) | /* h */
1148 ( srcval & 0x00ff00) | /* g */
1149 ((srcval << 16) & 0xff0000); /* l */
1151 srcbits = (char*)srcbits + srclinebytes;
1152 dstbits = (char*)dstbits + dstlinebytes;
1156 static void X11DRV_DIB_Convert_rgb888_to_any0888(int width, int height,
1157 const void* srcbits, int srclinebytes,
1158 void* dstbits, int dstlinebytes,
1159 DWORD rdst, DWORD gdst, DWORD bdst)
1161 int rLeftShift,gLeftShift,bLeftShift;
1162 const BYTE* srcpixel;
1163 DWORD* dstpixel;
1164 int x,y;
1166 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1167 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1168 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1169 for (y=0; y<height; y++) {
1170 srcpixel=srcbits;
1171 dstpixel=dstbits;
1172 for (x=0; x<width; x++) {
1173 *dstpixel++=(srcpixel[0] << bLeftShift) | /* b */
1174 (srcpixel[1] << gLeftShift) | /* g */
1175 (srcpixel[2] << rLeftShift); /* r */
1176 srcpixel+=3;
1178 srcbits = (char*)srcbits + srclinebytes;
1179 dstbits = (char*)dstbits + dstlinebytes;
1183 static void X11DRV_DIB_Convert_bgr888_to_any0888(int width, int height,
1184 const void* srcbits, int srclinebytes,
1185 void* dstbits, int dstlinebytes,
1186 DWORD rdst, DWORD gdst, DWORD bdst)
1188 int rLeftShift,gLeftShift,bLeftShift;
1189 const BYTE* srcpixel;
1190 DWORD* dstpixel;
1191 int x,y;
1193 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1194 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1195 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1196 for (y=0; y<height; y++) {
1197 srcpixel=srcbits;
1198 dstpixel=dstbits;
1199 for (x=0; x<width; x++) {
1200 *dstpixel++=(srcpixel[0] << rLeftShift) | /* r */
1201 (srcpixel[1] << gLeftShift) | /* g */
1202 (srcpixel[2] << bLeftShift); /* b */
1203 srcpixel+=3;
1205 srcbits = (char*)srcbits + srclinebytes;
1206 dstbits = (char*)dstbits + dstlinebytes;
1211 * 32 bit conversions
1214 static void X11DRV_DIB_Convert_0888_reverse(int width, int height,
1215 const void* srcbits, int srclinebytes,
1216 void* dstbits, int dstlinebytes)
1218 const DWORD* srcpixel;
1219 DWORD* dstpixel;
1220 int x,y;
1222 for (y=0; y<height; y++) {
1223 srcpixel=srcbits;
1224 dstpixel=dstbits;
1225 for (x=0; x<width; x++) {
1226 DWORD srcval;
1227 srcval=*srcpixel++;
1228 *dstpixel++=((srcval << 16) & 0x00ff0000) | /* h */
1229 ( srcval & 0x0000ff00) | /* g */
1230 ((srcval >> 16) & 0x000000ff); /* l */
1232 srcbits = (char*)srcbits + srclinebytes;
1233 dstbits = (char*)dstbits + dstlinebytes;
1237 static void X11DRV_DIB_Convert_0888_any(int width, int height,
1238 const void* srcbits, int srclinebytes,
1239 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1240 void* dstbits, int dstlinebytes,
1241 DWORD rdst, DWORD gdst, DWORD bdst)
1243 int rRightShift,gRightShift,bRightShift;
1244 int rLeftShift,gLeftShift,bLeftShift;
1245 const DWORD* srcpixel;
1246 DWORD* dstpixel;
1247 int x,y;
1249 rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1250 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1251 bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1252 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1253 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1254 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1255 for (y=0; y<height; y++) {
1256 srcpixel=srcbits;
1257 dstpixel=dstbits;
1258 for (x=0; x<width; x++) {
1259 DWORD srcval;
1260 srcval=*srcpixel++;
1261 *dstpixel++=(((srcval >> rRightShift) & 0xff) << rLeftShift) |
1262 (((srcval >> gRightShift) & 0xff) << gLeftShift) |
1263 (((srcval >> bRightShift) & 0xff) << bLeftShift);
1265 srcbits = (char*)srcbits + srclinebytes;
1266 dstbits = (char*)dstbits + dstlinebytes;
1270 static void X11DRV_DIB_Convert_0888_to_555_asis(int width, int height,
1271 const void* srcbits, int srclinebytes,
1272 void* dstbits, int dstlinebytes)
1274 const DWORD* srcpixel;
1275 WORD* dstpixel;
1276 int x,y;
1278 for (y=0; y<height; y++) {
1279 srcpixel=srcbits;
1280 dstpixel=dstbits;
1281 for (x=0; x<width; x++) {
1282 DWORD srcval;
1283 srcval=*srcpixel++;
1284 *dstpixel++=((srcval >> 9) & 0x7c00) | /* h */
1285 ((srcval >> 6) & 0x03e0) | /* g */
1286 ((srcval >> 3) & 0x001f); /* l */
1288 srcbits = (char*)srcbits + srclinebytes;
1289 dstbits = (char*)dstbits + dstlinebytes;
1293 static void X11DRV_DIB_Convert_0888_to_555_reverse(int width, int height,
1294 const void* srcbits, int srclinebytes,
1295 void* dstbits, int dstlinebytes)
1297 const DWORD* srcpixel;
1298 WORD* dstpixel;
1299 int x,y;
1301 for (y=0; y<height; y++) {
1302 srcpixel=srcbits;
1303 dstpixel=dstbits;
1304 for (x=0; x<width; x++) {
1305 DWORD srcval;
1306 srcval=*srcpixel++;
1307 *dstpixel++=((srcval >> 19) & 0x001f) | /* h */
1308 ((srcval >> 6) & 0x03e0) | /* g */
1309 ((srcval << 7) & 0x7c00); /* l */
1311 srcbits = (char*)srcbits + srclinebytes;
1312 dstbits = (char*)dstbits + dstlinebytes;
1316 static void X11DRV_DIB_Convert_0888_to_565_asis(int width, int height,
1317 const void* srcbits, int srclinebytes,
1318 void* dstbits, int dstlinebytes)
1320 const DWORD* srcpixel;
1321 WORD* dstpixel;
1322 int x,y;
1324 for (y=0; y<height; y++) {
1325 srcpixel=srcbits;
1326 dstpixel=dstbits;
1327 for (x=0; x<width; x++) {
1328 DWORD srcval;
1329 srcval=*srcpixel++;
1330 *dstpixel++=((srcval >> 8) & 0xf800) | /* h */
1331 ((srcval >> 5) & 0x07e0) | /* g */
1332 ((srcval >> 3) & 0x001f); /* l */
1334 srcbits = (char*)srcbits + srclinebytes;
1335 dstbits = (char*)dstbits + dstlinebytes;
1339 static void X11DRV_DIB_Convert_0888_to_565_reverse(int width, int height,
1340 const void* srcbits, int srclinebytes,
1341 void* dstbits, int dstlinebytes)
1343 const DWORD* srcpixel;
1344 WORD* dstpixel;
1345 int x,y;
1347 for (y=0; y<height; y++) {
1348 srcpixel=srcbits;
1349 dstpixel=dstbits;
1350 for (x=0; x<width; x++) {
1351 DWORD srcval;
1352 srcval=*srcpixel++;
1353 *dstpixel++=((srcval >> 19) & 0x001f) | /* h */
1354 ((srcval >> 5) & 0x07e0) | /* g */
1355 ((srcval << 8) & 0xf800); /* l */
1357 srcbits = (char*)srcbits + srclinebytes;
1358 dstbits = (char*)dstbits + dstlinebytes;
1362 static void X11DRV_DIB_Convert_any0888_to_5x5(int width, int height,
1363 const void* srcbits, int srclinebytes,
1364 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1365 void* dstbits, int dstlinebytes,
1366 WORD rdst, WORD gdst, WORD bdst)
1368 int rRightShift,gRightShift,bRightShift;
1369 int rLeftShift,gLeftShift,bLeftShift;
1370 const DWORD* srcpixel;
1371 WORD* dstpixel;
1372 int x,y;
1374 /* Here is how we proceed. Assume we have rsrc=0x0000ff00 and our pixel
1375 * contains 0x11223344.
1376 * - first we shift 0x11223344 right by rRightShift to bring the most
1377 * significant bits of the red components in the bottom 5 (or 6) bits
1378 * -> 0x4488c
1379 * - then we remove non red bits by anding with the modified rdst (0x1f)
1380 * -> 0x0c
1381 * - finally shift these bits left by rLeftShift so that they end up in
1382 * the right place
1383 * -> 0x3000
1385 rRightShift=X11DRV_DIB_MaskToShift(rsrc)+3;
1386 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1387 gRightShift+=(gdst==0x07e0?2:3);
1388 bRightShift=X11DRV_DIB_MaskToShift(bsrc)+3;
1390 rLeftShift=X11DRV_DIB_MaskToShift(rdst);
1391 rdst=rdst >> rLeftShift;
1392 gLeftShift=X11DRV_DIB_MaskToShift(gdst);
1393 gdst=gdst >> gLeftShift;
1394 bLeftShift=X11DRV_DIB_MaskToShift(bdst);
1395 bdst=bdst >> bLeftShift;
1397 for (y=0; y<height; y++) {
1398 srcpixel=srcbits;
1399 dstpixel=dstbits;
1400 for (x=0; x<width; x++) {
1401 DWORD srcval;
1402 srcval=*srcpixel++;
1403 *dstpixel++=(((srcval >> rRightShift) & rdst) << rLeftShift) |
1404 (((srcval >> gRightShift) & gdst) << gLeftShift) |
1405 (((srcval >> bRightShift) & bdst) << bLeftShift);
1407 srcbits = (char*)srcbits + srclinebytes;
1408 dstbits = (char*)dstbits + dstlinebytes;
1412 static void X11DRV_DIB_Convert_0888_to_888_asis(int width, int height,
1413 const void* srcbits, int srclinebytes,
1414 void* dstbits, int dstlinebytes)
1416 const DWORD* srcpixel;
1417 DWORD* dstpixel;
1418 BYTE* dstbyte;
1419 int x,y;
1420 int oddwidth;
1422 oddwidth=width & 3;
1423 width=width/4;
1424 for (y=0; y<height; y++) {
1425 srcpixel=srcbits;
1426 dstpixel=dstbits;
1427 for (x=0; x<width; x++) {
1428 /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */
1429 DWORD srcval;
1430 srcval=((*srcpixel++) & 0x00ffffff); /* h1, g1, l1*/
1431 *dstpixel++=srcval | ((*srcpixel) << 24); /* h2 */
1432 srcval=((*srcpixel++ >> 8 ) & 0x0000ffff); /* g2, l2 */
1433 *dstpixel++=srcval | ((*srcpixel) << 16); /* h3, g3 */
1434 srcval=((*srcpixel++ >> 16) & 0x000000ff); /* l3 */
1435 *dstpixel++=srcval | ((*srcpixel++) << 8); /* h4, g4, l4 */
1437 /* And now up to 3 odd pixels */
1438 dstbyte=(BYTE*)dstpixel;
1439 for (x=0; x<oddwidth; x++) {
1440 DWORD srcval;
1441 srcval=*srcpixel++;
1442 *((WORD*)dstbyte)++=srcval; /* h, g */
1443 *dstbyte++=srcval >> 16; /* l */
1445 srcbits = (char*)srcbits + srclinebytes;
1446 dstbits = (char*)dstbits + dstlinebytes;
1450 static void X11DRV_DIB_Convert_0888_to_888_reverse(int width, int height,
1451 const void* srcbits, int srclinebytes,
1452 void* dstbits, int dstlinebytes)
1454 const DWORD* srcpixel;
1455 DWORD* dstpixel;
1456 BYTE* dstbyte;
1457 int x,y;
1458 int oddwidth;
1460 oddwidth=width & 3;
1461 width=width/4;
1462 for (y=0; y<height; y++) {
1463 srcpixel=srcbits;
1464 dstpixel=dstbits;
1465 for (x=0; x<width; x++) {
1466 /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */
1467 DWORD srcval1,srcval2;
1468 srcval1=*srcpixel++;
1469 srcval2= ((srcval1 >> 16) & 0x000000ff) | /* h1 */
1470 ( srcval1 & 0x0000ff00) | /* g1 */
1471 ((srcval1 << 16) & 0x00ff0000); /* l1 */
1472 srcval1=*srcpixel++;
1473 *dstpixel++=srcval2 |
1474 ((srcval1 << 8) & 0xff000000); /* h2 */
1475 srcval2= ((srcval1 >> 8) & 0x000000ff) | /* g2 */
1476 ((srcval1 << 8) & 0x0000ff00); /* l2 */
1477 srcval1=*srcpixel++;
1478 *dstpixel++=srcval2 |
1479 ( srcval1 & 0x00ff0000) | /* h3 */
1480 ((srcval1 << 16) & 0xff000000); /* g3 */
1481 srcval2= ( srcval1 & 0x000000ff); /* l3 */
1482 srcval1=*srcpixel++;
1483 *dstpixel++=srcval2 |
1484 ((srcval1 >> 8) & 0x0000ff00) | /* h4 */
1485 ((srcval1 << 8) & 0x00ff0000) | /* g4 */
1486 ( srcval1 << 24); /* l4 */
1488 /* And now up to 3 odd pixels */
1489 dstbyte=(BYTE*)dstpixel;
1490 for (x=0; x<oddwidth; x++) {
1491 DWORD srcval;
1492 srcval=*srcpixel++;
1493 *((WORD*)dstbyte)++=((srcval >> 16) & 0x00ff) | /* h */
1494 (srcval & 0xff00); /* g */
1495 *dstbyte++=srcval; /* l */
1497 srcbits = (char*)srcbits + srclinebytes;
1498 dstbits = (char*)dstbits + dstlinebytes;
1502 static void X11DRV_DIB_Convert_any0888_to_rgb888(int width, int height,
1503 const void* srcbits, int srclinebytes,
1504 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1505 void* dstbits, int dstlinebytes)
1507 int rRightShift,gRightShift,bRightShift;
1508 const DWORD* srcpixel;
1509 BYTE* dstpixel;
1510 int x,y;
1512 rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1513 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1514 bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1515 for (y=0; y<height; y++) {
1516 srcpixel=srcbits;
1517 dstpixel=dstbits;
1518 for (x=0; x<width; x++) {
1519 DWORD srcval;
1520 srcval=*srcpixel++;
1521 dstpixel[0]=(srcval >> bRightShift); /* b */
1522 dstpixel[1]=(srcval >> gRightShift); /* g */
1523 dstpixel[2]=(srcval >> rRightShift); /* r */
1524 dstpixel+=3;
1526 srcbits = (char*)srcbits + srclinebytes;
1527 dstbits = (char*)dstbits + dstlinebytes;
1531 static void X11DRV_DIB_Convert_any0888_to_bgr888(int width, int height,
1532 const void* srcbits, int srclinebytes,
1533 DWORD rsrc, DWORD gsrc, DWORD bsrc,
1534 void* dstbits, int dstlinebytes)
1536 int rRightShift,gRightShift,bRightShift;
1537 const DWORD* srcpixel;
1538 BYTE* dstpixel;
1539 int x,y;
1541 rRightShift=X11DRV_DIB_MaskToShift(rsrc);
1542 gRightShift=X11DRV_DIB_MaskToShift(gsrc);
1543 bRightShift=X11DRV_DIB_MaskToShift(bsrc);
1544 for (y=0; y<height; y++) {
1545 srcpixel=srcbits;
1546 dstpixel=dstbits;
1547 for (x=0; x<width; x++) {
1548 DWORD srcval;
1549 srcval=*srcpixel++;
1550 dstpixel[0]=(srcval >> rRightShift); /* r */
1551 dstpixel[1]=(srcval >> gRightShift); /* g */
1552 dstpixel[2]=(srcval >> bRightShift); /* b */
1553 dstpixel+=3;
1555 srcbits = (char*)srcbits + srclinebytes;
1556 dstbits = (char*)dstbits + dstlinebytes;
1560 /***********************************************************************
1561 * X11DRV_DIB_SetImageBits_1
1563 * SetDIBits for a 1-bit deep DIB.
1565 static void X11DRV_DIB_SetImageBits_1( int lines, const BYTE *srcbits,
1566 DWORD srcwidth, DWORD dstwidth, int left,
1567 int *colors, XImage *bmpImage, DWORD linebytes)
1569 int h;
1570 const BYTE* srcbyte;
1571 BYTE srcval, extra;
1572 DWORD i, x;
1574 if (lines < 0 ) {
1575 lines = -lines;
1576 srcbits = srcbits + linebytes * (lines - 1);
1577 linebytes = -linebytes;
1580 if ((extra = (left & 7)) != 0) {
1581 left &= ~7;
1582 dstwidth += extra;
1584 srcbits += left >> 3;
1586 /* ==== pal 1 dib -> any bmp format ==== */
1587 for (h = lines-1; h >=0; h--) {
1588 srcbyte=srcbits;
1589 /* FIXME: should avoid putting x<left pixels (minor speed issue) */
1590 for (i = dstwidth/8, x = left; i > 0; i--) {
1591 srcval=*srcbyte++;
1592 XPutPixel( bmpImage, x++, h, colors[ srcval >> 7] );
1593 XPutPixel( bmpImage, x++, h, colors[(srcval >> 6) & 1] );
1594 XPutPixel( bmpImage, x++, h, colors[(srcval >> 5) & 1] );
1595 XPutPixel( bmpImage, x++, h, colors[(srcval >> 4) & 1] );
1596 XPutPixel( bmpImage, x++, h, colors[(srcval >> 3) & 1] );
1597 XPutPixel( bmpImage, x++, h, colors[(srcval >> 2) & 1] );
1598 XPutPixel( bmpImage, x++, h, colors[(srcval >> 1) & 1] );
1599 XPutPixel( bmpImage, x++, h, colors[ srcval & 1] );
1601 srcval=*srcbyte;
1602 switch (dstwidth & 7)
1604 case 7: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1605 case 6: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1606 case 5: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1607 case 4: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1608 case 3: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1609 case 2: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]); srcval<<=1;
1610 case 1: XPutPixel(bmpImage, x++, h, colors[srcval >> 7]);
1612 srcbits += linebytes;
1616 /***********************************************************************
1617 * X11DRV_DIB_GetImageBits_1
1619 * GetDIBits for a 1-bit deep DIB.
1621 static void X11DRV_DIB_GetImageBits_1( int lines, BYTE *dstbits,
1622 DWORD dstwidth, DWORD srcwidth,
1623 RGBQUAD *colors, PALETTEENTRY *srccolors,
1624 XImage *bmpImage, DWORD linebytes )
1626 DWORD x;
1627 int h;
1629 if (lines < 0 ) {
1630 lines = -lines;
1631 dstbits = dstbits + linebytes * (lines - 1);
1632 linebytes = -linebytes;
1635 switch (bmpImage->depth)
1637 case 1:
1638 case 4:
1639 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1640 /* ==== pal 1 or 4 bmp -> pal 1 dib ==== */
1641 BYTE* dstbyte;
1643 for (h=lines-1; h>=0; h--) {
1644 BYTE dstval;
1645 dstbyte=dstbits;
1646 dstval=0;
1647 for (x=0; x<dstwidth; x++) {
1648 PALETTEENTRY srcval;
1649 srcval=srccolors[XGetPixel(bmpImage, x, h)];
1650 dstval|=(X11DRV_DIB_GetNearestIndex
1651 (colors, 2,
1652 srcval.peRed,
1653 srcval.peGreen,
1654 srcval.peBlue) << (7 - (x & 7)));
1655 if ((x&7)==7) {
1656 *dstbyte++=dstval;
1657 dstval=0;
1660 if ((dstwidth&7)!=0) {
1661 *dstbyte=dstval;
1663 dstbits += linebytes;
1665 } else {
1666 goto notsupported;
1668 break;
1670 case 8:
1671 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
1672 /* ==== pal 8 bmp -> pal 1 dib ==== */
1673 const void* srcbits;
1674 const BYTE* srcpixel;
1675 BYTE* dstbyte;
1677 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1679 for (h=0; h<lines; h++) {
1680 BYTE dstval;
1681 srcpixel=srcbits;
1682 dstbyte=dstbits;
1683 dstval=0;
1684 for (x=0; x<dstwidth; x++) {
1685 PALETTEENTRY srcval;
1686 srcval=srccolors[(int)*srcpixel++];
1687 dstval|=(X11DRV_DIB_GetNearestIndex
1688 (colors, 2,
1689 srcval.peRed,
1690 srcval.peGreen,
1691 srcval.peBlue) << (7-(x&7)) );
1692 if ((x&7)==7) {
1693 *dstbyte++=dstval;
1694 dstval=0;
1697 if ((dstwidth&7)!=0) {
1698 *dstbyte=dstval;
1700 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1701 dstbits += linebytes;
1703 } else {
1704 goto notsupported;
1706 break;
1708 case 15:
1709 case 16:
1711 const void* srcbits;
1712 const WORD* srcpixel;
1713 BYTE* dstbyte;
1715 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1717 if (bmpImage->green_mask==0x03e0) {
1718 if (bmpImage->red_mask==0x7c00) {
1719 /* ==== rgb 555 bmp -> pal 1 dib ==== */
1720 for (h=0; h<lines; h++) {
1721 BYTE dstval;
1722 srcpixel=srcbits;
1723 dstbyte=dstbits;
1724 dstval=0;
1725 for (x=0; x<dstwidth; x++) {
1726 WORD srcval;
1727 srcval=*srcpixel++;
1728 dstval|=(X11DRV_DIB_GetNearestIndex
1729 (colors, 2,
1730 ((srcval >> 7) & 0xf8) | /* r */
1731 ((srcval >> 12) & 0x07),
1732 ((srcval >> 2) & 0xf8) | /* g */
1733 ((srcval >> 7) & 0x07),
1734 ((srcval << 3) & 0xf8) | /* b */
1735 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
1736 if ((x&7)==7) {
1737 *dstbyte++=dstval;
1738 dstval=0;
1741 if ((dstwidth&7)!=0) {
1742 *dstbyte=dstval;
1744 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1745 dstbits += linebytes;
1747 } else if (bmpImage->blue_mask==0x7c00) {
1748 /* ==== bgr 555 bmp -> pal 1 dib ==== */
1749 for (h=0; h<lines; h++) {
1750 WORD dstval;
1751 srcpixel=srcbits;
1752 dstbyte=dstbits;
1753 dstval=0;
1754 for (x=0; x<dstwidth; x++) {
1755 BYTE srcval;
1756 srcval=*srcpixel++;
1757 dstval|=(X11DRV_DIB_GetNearestIndex
1758 (colors, 2,
1759 ((srcval << 3) & 0xf8) | /* r */
1760 ((srcval >> 2) & 0x07),
1761 ((srcval >> 2) & 0xf8) | /* g */
1762 ((srcval >> 7) & 0x07),
1763 ((srcval >> 7) & 0xf8) | /* b */
1764 ((srcval >> 12) & 0x07) ) << (7-(x&7)) );
1765 if ((x&7)==7) {
1766 *dstbyte++=dstval;
1767 dstval=0;
1770 if ((dstwidth&7)!=0) {
1771 *dstbyte=dstval;
1773 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1774 dstbits += linebytes;
1776 } else {
1777 goto notsupported;
1779 } else if (bmpImage->green_mask==0x07e0) {
1780 if (bmpImage->red_mask==0xf800) {
1781 /* ==== rgb 565 bmp -> pal 1 dib ==== */
1782 for (h=0; h<lines; h++) {
1783 BYTE dstval;
1784 srcpixel=srcbits;
1785 dstbyte=dstbits;
1786 dstval=0;
1787 for (x=0; x<dstwidth; x++) {
1788 WORD srcval;
1789 srcval=*srcpixel++;
1790 dstval|=(X11DRV_DIB_GetNearestIndex
1791 (colors, 2,
1792 ((srcval >> 8) & 0xf8) | /* r */
1793 ((srcval >> 13) & 0x07),
1794 ((srcval >> 3) & 0xfc) | /* g */
1795 ((srcval >> 9) & 0x03),
1796 ((srcval << 3) & 0xf8) | /* b */
1797 ((srcval >> 2) & 0x07) ) << (7-(x&7)) );
1798 if ((x&7)==7) {
1799 *dstbyte++=dstval;
1800 dstval=0;
1803 if ((dstwidth&7)!=0) {
1804 *dstbyte=dstval;
1806 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1807 dstbits += linebytes;
1809 } else if (bmpImage->blue_mask==0xf800) {
1810 /* ==== bgr 565 bmp -> pal 1 dib ==== */
1811 for (h=0; h<lines; h++) {
1812 BYTE dstval;
1813 srcpixel=srcbits;
1814 dstbyte=dstbits;
1815 dstval=0;
1816 for (x=0; x<dstwidth; x++) {
1817 WORD srcval;
1818 srcval=*srcpixel++;
1819 dstval|=(X11DRV_DIB_GetNearestIndex
1820 (colors, 2,
1821 ((srcval << 3) & 0xf8) | /* r */
1822 ((srcval >> 2) & 0x07),
1823 ((srcval >> 3) & 0xfc) | /* g */
1824 ((srcval >> 9) & 0x03),
1825 ((srcval >> 8) & 0xf8) | /* b */
1826 ((srcval >> 13) & 0x07) ) << (7-(x&7)) );
1827 if ((x&7)==7) {
1828 *dstbyte++=dstval;
1829 dstval=0;
1832 if ((dstwidth&7)!=0) {
1833 *dstbyte=dstval;
1835 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1836 dstbits += linebytes;
1838 } else {
1839 goto notsupported;
1841 } else {
1842 goto notsupported;
1845 break;
1847 case 24:
1848 case 32:
1850 const void* srcbits;
1851 const BYTE *srcbyte;
1852 BYTE* dstbyte;
1853 int bytes_per_pixel;
1855 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
1856 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
1858 if (bmpImage->green_mask!=0x00ff00 ||
1859 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
1860 goto notsupported;
1861 } else if (bmpImage->blue_mask==0xff) {
1862 /* ==== rgb 888 or 0888 bmp -> pal 1 dib ==== */
1863 for (h=0; h<lines; h++) {
1864 BYTE dstval;
1865 srcbyte=srcbits;
1866 dstbyte=dstbits;
1867 dstval=0;
1868 for (x=0; x<dstwidth; x++) {
1869 dstval|=(X11DRV_DIB_GetNearestIndex
1870 (colors, 2,
1871 srcbyte[2],
1872 srcbyte[1],
1873 srcbyte[0]) << (7-(x&7)) );
1874 srcbyte+=bytes_per_pixel;
1875 if ((x&7)==7) {
1876 *dstbyte++=dstval;
1877 dstval=0;
1880 if ((dstwidth&7)!=0) {
1881 *dstbyte=dstval;
1883 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1884 dstbits += linebytes;
1886 } else {
1887 /* ==== bgr 888 or 0888 bmp -> pal 1 dib ==== */
1888 for (h=0; h<lines; h++) {
1889 BYTE dstval;
1890 srcbyte=srcbits;
1891 dstbyte=dstbits;
1892 dstval=0;
1893 for (x=0; x<dstwidth; x++) {
1894 dstval|=(X11DRV_DIB_GetNearestIndex
1895 (colors, 2,
1896 srcbyte[0],
1897 srcbyte[1],
1898 srcbyte[2]) << (7-(x&7)) );
1899 srcbyte+=bytes_per_pixel;
1900 if ((x&7)==7) {
1901 *dstbyte++=dstval;
1902 dstval=0;
1905 if ((dstwidth&7)!=0) {
1906 *dstbyte=dstval;
1908 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
1909 dstbits += linebytes;
1913 break;
1915 default:
1916 notsupported:
1918 BYTE* dstbyte;
1919 unsigned long white = (1 << bmpImage->bits_per_pixel) - 1;
1921 /* ==== any bmp format -> pal 1 dib ==== */
1922 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 1 bit DIB\n",
1923 bmpImage->bits_per_pixel, bmpImage->red_mask,
1924 bmpImage->green_mask, bmpImage->blue_mask );
1926 for (h=lines-1; h>=0; h--) {
1927 BYTE dstval;
1928 dstbyte=dstbits;
1929 dstval=0;
1930 for (x=0; x<dstwidth; x++) {
1931 dstval|=(XGetPixel( bmpImage, x, h) >= white) << (7 - (x&7));
1932 if ((x&7)==7) {
1933 *dstbyte++=dstval;
1934 dstval=0;
1937 if ((dstwidth&7)!=0) {
1938 *dstbyte=dstval;
1940 dstbits += linebytes;
1943 break;
1947 /***********************************************************************
1948 * X11DRV_DIB_SetImageBits_4
1950 * SetDIBits for a 4-bit deep DIB.
1952 static void X11DRV_DIB_SetImageBits_4( int lines, const BYTE *srcbits,
1953 DWORD srcwidth, DWORD dstwidth, int left,
1954 int *colors, XImage *bmpImage, DWORD linebytes)
1956 int h;
1957 const BYTE* srcbyte;
1958 DWORD i, x;
1960 if (lines < 0 ) {
1961 lines = -lines;
1962 srcbits = srcbits + linebytes * (lines - 1);
1963 linebytes = -linebytes;
1966 if (left & 1) {
1967 left--;
1968 dstwidth++;
1970 srcbits += left >> 1;
1972 /* ==== pal 4 dib -> any bmp format ==== */
1973 for (h = lines-1; h >= 0; h--) {
1974 srcbyte=srcbits;
1975 for (i = dstwidth/2, x = left; i > 0; i--) {
1976 BYTE srcval=*srcbyte++;
1977 XPutPixel( bmpImage, x++, h, colors[srcval >> 4] );
1978 XPutPixel( bmpImage, x++, h, colors[srcval & 0x0f] );
1980 if (dstwidth & 1)
1981 XPutPixel( bmpImage, x, h, colors[*srcbyte >> 4] );
1982 srcbits += linebytes;
1988 /***********************************************************************
1989 * X11DRV_DIB_GetImageBits_4
1991 * GetDIBits for a 4-bit deep DIB.
1993 static void X11DRV_DIB_GetImageBits_4( int lines, BYTE *dstbits,
1994 DWORD srcwidth, DWORD dstwidth,
1995 RGBQUAD *colors, PALETTEENTRY *srccolors,
1996 XImage *bmpImage, DWORD linebytes )
1998 DWORD x;
1999 int h;
2000 BYTE *bits;
2002 if (lines < 0 )
2004 lines = -lines;
2005 dstbits = dstbits + ( linebytes * (lines-1) );
2006 linebytes = -linebytes;
2009 bits = dstbits;
2011 switch (bmpImage->depth) {
2012 case 1:
2013 case 4:
2014 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2015 /* ==== pal 1 or 4 bmp -> pal 4 dib ==== */
2016 BYTE* dstbyte;
2018 for (h = lines-1; h >= 0; h--) {
2019 BYTE dstval;
2020 dstbyte=dstbits;
2021 dstval=0;
2022 for (x = 0; x < dstwidth; x++) {
2023 PALETTEENTRY srcval;
2024 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2025 dstval|=(X11DRV_DIB_GetNearestIndex
2026 (colors, 16,
2027 srcval.peRed,
2028 srcval.peGreen,
2029 srcval.peBlue) << (4-((x&1)<<2)));
2030 if ((x&1)==1) {
2031 *dstbyte++=dstval;
2032 dstval=0;
2035 if ((dstwidth&1)!=0) {
2036 *dstbyte=dstval;
2038 dstbits += linebytes;
2040 } else {
2041 goto notsupported;
2043 break;
2045 case 8:
2046 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2047 /* ==== pal 8 bmp -> pal 4 dib ==== */
2048 const void* srcbits;
2049 const BYTE *srcpixel;
2050 BYTE* dstbyte;
2052 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2053 for (h=0; h<lines; h++) {
2054 BYTE dstval;
2055 srcpixel=srcbits;
2056 dstbyte=dstbits;
2057 dstval=0;
2058 for (x=0; x<dstwidth; x++) {
2059 PALETTEENTRY srcval;
2060 srcval = srccolors[(int)*srcpixel++];
2061 dstval|=(X11DRV_DIB_GetNearestIndex
2062 (colors, 16,
2063 srcval.peRed,
2064 srcval.peGreen,
2065 srcval.peBlue) << (4*(1-(x&1))) );
2066 if ((x&1)==1) {
2067 *dstbyte++=dstval;
2068 dstval=0;
2071 if ((dstwidth&1)!=0) {
2072 *dstbyte=dstval;
2074 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2075 dstbits += linebytes;
2077 } else {
2078 goto notsupported;
2080 break;
2082 case 15:
2083 case 16:
2085 const void* srcbits;
2086 const WORD* srcpixel;
2087 BYTE* dstbyte;
2089 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2091 if (bmpImage->green_mask==0x03e0) {
2092 if (bmpImage->red_mask==0x7c00) {
2093 /* ==== rgb 555 bmp -> pal 4 dib ==== */
2094 for (h=0; h<lines; h++) {
2095 BYTE dstval;
2096 srcpixel=srcbits;
2097 dstbyte=dstbits;
2098 dstval=0;
2099 for (x=0; x<dstwidth; x++) {
2100 WORD srcval;
2101 srcval=*srcpixel++;
2102 dstval|=(X11DRV_DIB_GetNearestIndex
2103 (colors, 16,
2104 ((srcval >> 7) & 0xf8) | /* r */
2105 ((srcval >> 12) & 0x07),
2106 ((srcval >> 2) & 0xf8) | /* g */
2107 ((srcval >> 7) & 0x07),
2108 ((srcval << 3) & 0xf8) | /* b */
2109 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
2110 if ((x&1)==1) {
2111 *dstbyte++=dstval;
2112 dstval=0;
2115 if ((dstwidth&1)!=0) {
2116 *dstbyte=dstval;
2118 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2119 dstbits += linebytes;
2121 } else if (bmpImage->blue_mask==0x7c00) {
2122 /* ==== bgr 555 bmp -> pal 4 dib ==== */
2123 for (h=0; h<lines; h++) {
2124 WORD dstval;
2125 srcpixel=srcbits;
2126 dstbyte=dstbits;
2127 dstval=0;
2128 for (x=0; x<dstwidth; x++) {
2129 WORD srcval;
2130 srcval=*srcpixel++;
2131 dstval|=(X11DRV_DIB_GetNearestIndex
2132 (colors, 16,
2133 ((srcval << 3) & 0xf8) | /* r */
2134 ((srcval >> 2) & 0x07),
2135 ((srcval >> 2) & 0xf8) | /* g */
2136 ((srcval >> 7) & 0x07),
2137 ((srcval >> 7) & 0xf8) | /* b */
2138 ((srcval >> 12) & 0x07) ) << ((1-(x&1))<<2) );
2139 if ((x&1)==1) {
2140 *dstbyte++=dstval;
2141 dstval=0;
2144 if ((dstwidth&1)!=0) {
2145 *dstbyte=dstval;
2147 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2148 dstbits += linebytes;
2150 } else {
2151 goto notsupported;
2153 } else if (bmpImage->green_mask==0x07e0) {
2154 if (bmpImage->red_mask==0xf800) {
2155 /* ==== rgb 565 bmp -> pal 4 dib ==== */
2156 for (h=0; h<lines; h++) {
2157 BYTE dstval;
2158 srcpixel=srcbits;
2159 dstbyte=dstbits;
2160 dstval=0;
2161 for (x=0; x<dstwidth; x++) {
2162 WORD srcval;
2163 srcval=*srcpixel++;
2164 dstval|=(X11DRV_DIB_GetNearestIndex
2165 (colors, 16,
2166 ((srcval >> 8) & 0xf8) | /* r */
2167 ((srcval >> 13) & 0x07),
2168 ((srcval >> 3) & 0xfc) | /* g */
2169 ((srcval >> 9) & 0x03),
2170 ((srcval << 3) & 0xf8) | /* b */
2171 ((srcval >> 2) & 0x07) ) << ((1-(x&1))<<2) );
2172 if ((x&1)==1) {
2173 *dstbyte++=dstval;
2174 dstval=0;
2177 if ((dstwidth&1)!=0) {
2178 *dstbyte=dstval;
2180 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2181 dstbits += linebytes;
2183 } else if (bmpImage->blue_mask==0xf800) {
2184 /* ==== bgr 565 bmp -> pal 4 dib ==== */
2185 for (h=0; h<lines; h++) {
2186 WORD dstval;
2187 srcpixel=srcbits;
2188 dstbyte=dstbits;
2189 dstval=0;
2190 for (x=0; x<dstwidth; x++) {
2191 WORD srcval;
2192 srcval=*srcpixel++;
2193 dstval|=(X11DRV_DIB_GetNearestIndex
2194 (colors, 16,
2195 ((srcval << 3) & 0xf8) | /* r */
2196 ((srcval >> 2) & 0x07),
2197 ((srcval >> 3) & 0xfc) | /* g */
2198 ((srcval >> 9) & 0x03),
2199 ((srcval >> 8) & 0xf8) | /* b */
2200 ((srcval >> 13) & 0x07) ) << ((1-(x&1))<<2) );
2201 if ((x&1)==1) {
2202 *dstbyte++=dstval;
2203 dstval=0;
2206 if ((dstwidth&1)!=0) {
2207 *dstbyte=dstval;
2209 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2210 dstbits += linebytes;
2212 } else {
2213 goto notsupported;
2215 } else {
2216 goto notsupported;
2219 break;
2221 case 24:
2222 if (bmpImage->bits_per_pixel==24) {
2223 const void* srcbits;
2224 const BYTE *srcbyte;
2225 BYTE* dstbyte;
2227 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2229 if (bmpImage->green_mask!=0x00ff00 ||
2230 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2231 goto notsupported;
2232 } else if (bmpImage->blue_mask==0xff) {
2233 /* ==== rgb 888 bmp -> pal 4 dib ==== */
2234 for (h=0; h<lines; h++) {
2235 srcbyte=srcbits;
2236 dstbyte=dstbits;
2237 for (x=0; x<dstwidth/2; x++) {
2238 /* Do 2 pixels at a time */
2239 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2240 (colors, 16,
2241 srcbyte[2],
2242 srcbyte[1],
2243 srcbyte[0]) << 4) |
2244 X11DRV_DIB_GetNearestIndex
2245 (colors, 16,
2246 srcbyte[5],
2247 srcbyte[4],
2248 srcbyte[3]);
2249 srcbyte+=6;
2251 if (dstwidth&1) {
2252 /* And the the odd pixel */
2253 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2254 (colors, 16,
2255 srcbyte[2],
2256 srcbyte[1],
2257 srcbyte[0]) << 4);
2259 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2260 dstbits += linebytes;
2262 } else {
2263 /* ==== bgr 888 bmp -> pal 4 dib ==== */
2264 for (h=0; h<lines; h++) {
2265 srcbyte=srcbits;
2266 dstbyte=dstbits;
2267 for (x=0; x<dstwidth/2; x++) {
2268 /* Do 2 pixels at a time */
2269 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2270 (colors, 16,
2271 srcbyte[0],
2272 srcbyte[1],
2273 srcbyte[2]) << 4) |
2274 X11DRV_DIB_GetNearestIndex
2275 (colors, 16,
2276 srcbyte[3],
2277 srcbyte[4],
2278 srcbyte[5]);
2279 srcbyte+=6;
2281 if (dstwidth&1) {
2282 /* And the the odd pixel */
2283 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2284 (colors, 16,
2285 srcbyte[0],
2286 srcbyte[1],
2287 srcbyte[2]) << 4);
2289 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2290 dstbits += linebytes;
2293 break;
2295 /* Fall through */
2297 case 32:
2299 const void* srcbits;
2300 const BYTE *srcbyte;
2301 BYTE* dstbyte;
2303 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2305 if (bmpImage->green_mask!=0x00ff00 ||
2306 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2307 goto notsupported;
2308 } else if (bmpImage->blue_mask==0xff) {
2309 /* ==== rgb 0888 bmp -> pal 4 dib ==== */
2310 for (h=0; h<lines; h++) {
2311 srcbyte=srcbits;
2312 dstbyte=dstbits;
2313 for (x=0; x<dstwidth/2; x++) {
2314 /* Do 2 pixels at a time */
2315 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2316 (colors, 16,
2317 srcbyte[2],
2318 srcbyte[1],
2319 srcbyte[0]) << 4) |
2320 X11DRV_DIB_GetNearestIndex
2321 (colors, 16,
2322 srcbyte[6],
2323 srcbyte[5],
2324 srcbyte[4]);
2325 srcbyte+=8;
2327 if (dstwidth&1) {
2328 /* And the the odd pixel */
2329 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2330 (colors, 16,
2331 srcbyte[2],
2332 srcbyte[1],
2333 srcbyte[0]) << 4);
2335 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2336 dstbits += linebytes;
2338 } else {
2339 /* ==== bgr 0888 bmp -> pal 4 dib ==== */
2340 for (h=0; h<lines; h++) {
2341 srcbyte=srcbits;
2342 dstbyte=dstbits;
2343 for (x=0; x<dstwidth/2; x++) {
2344 /* Do 2 pixels at a time */
2345 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2346 (colors, 16,
2347 srcbyte[0],
2348 srcbyte[1],
2349 srcbyte[2]) << 4) |
2350 X11DRV_DIB_GetNearestIndex
2351 (colors, 16,
2352 srcbyte[4],
2353 srcbyte[5],
2354 srcbyte[6]);
2355 srcbyte+=8;
2357 if (dstwidth&1) {
2358 /* And the the odd pixel */
2359 *dstbyte++=(X11DRV_DIB_GetNearestIndex
2360 (colors, 16,
2361 srcbyte[0],
2362 srcbyte[1],
2363 srcbyte[2]) << 4);
2365 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2366 dstbits += linebytes;
2370 break;
2372 default:
2373 notsupported:
2375 BYTE* dstbyte;
2377 /* ==== any bmp format -> pal 4 dib ==== */
2378 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 4 bit DIB\n",
2379 bmpImage->bits_per_pixel, bmpImage->red_mask,
2380 bmpImage->green_mask, bmpImage->blue_mask );
2381 for (h=lines-1; h>=0; h--) {
2382 dstbyte=dstbits;
2383 for (x=0; x<(dstwidth & ~1); x+=2) {
2384 *dstbyte++=(X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4) |
2385 X11DRV_DIB_MapColor((int*)colors, 16, XGetPixel(bmpImage, x+1, h), 0);
2387 if (dstwidth & 1) {
2388 *dstbyte=(X11DRV_DIB_MapColor((int *)colors, 16, XGetPixel(bmpImage, x, h), 0) << 4);
2390 dstbits += linebytes;
2393 break;
2397 /***********************************************************************
2398 * X11DRV_DIB_SetImageBits_RLE4
2400 * SetDIBits for a 4-bit deep compressed DIB.
2402 static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
2403 DWORD width, DWORD dstwidth,
2404 int left, int *colors,
2405 XImage *bmpImage )
2407 int x = 0, y = lines - 1, c, length;
2408 const BYTE *begin = bits;
2410 while (y >= 0)
2412 length = *bits++;
2413 if (length) { /* encoded */
2414 c = *bits++;
2415 while (length--) {
2416 if (x >= width) break;
2417 XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2418 if (!length--) break;
2419 if (x >= width) break;
2420 XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2422 } else {
2423 length = *bits++;
2424 switch (length)
2426 case RLE_EOL:
2427 x = 0;
2428 y--;
2429 break;
2431 case RLE_END:
2432 return;
2434 case RLE_DELTA:
2435 x += *bits++;
2436 y -= *bits++;
2437 break;
2439 default: /* absolute */
2440 while (length--) {
2441 c = *bits++;
2442 if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
2443 if (!length--) break;
2444 if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
2446 if ((bits - begin) & 1)
2447 bits++;
2455 /***********************************************************************
2456 * X11DRV_DIB_SetImageBits_8
2458 * SetDIBits for an 8-bit deep DIB.
2460 static void X11DRV_DIB_SetImageBits_8( int lines, const BYTE *srcbits,
2461 DWORD srcwidth, DWORD dstwidth, int left,
2462 const int *colors, XImage *bmpImage,
2463 DWORD linebytes )
2465 DWORD x;
2466 int h;
2467 const BYTE* srcbyte;
2468 BYTE* dstbits;
2470 if (lines < 0 )
2472 lines = -lines;
2473 srcbits = srcbits + linebytes * (lines-1);
2474 linebytes = -linebytes;
2476 srcbits += left;
2477 srcbyte = srcbits;
2479 switch (bmpImage->depth) {
2480 case 15:
2481 case 16:
2482 #if defined(__i386__) && defined(__GNUC__)
2483 /* Some X servers might have 32 bit/ 16bit deep pixel */
2484 if (lines && dstwidth && (bmpImage->bits_per_pixel == 16) &&
2485 (ImageByteOrder(gdi_display)==LSBFirst) )
2487 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2488 /* FIXME: Does this really handle all these cases correctly? */
2489 /* ==== pal 8 dib -> rgb or bgr 555 or 565 bmp ==== */
2490 for (h = lines ; h--; ) {
2491 int _cl1,_cl2; /* temp outputs for asm below */
2492 /* Borrowed from DirectDraw */
2493 __asm__ __volatile__(
2494 "xor %%eax,%%eax\n"
2495 "cld\n"
2496 "1:\n"
2497 " lodsb\n"
2498 " movw (%%edx,%%eax,4),%%ax\n"
2499 " stosw\n"
2500 " xor %%eax,%%eax\n"
2501 " loop 1b\n"
2502 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2503 :"S" (srcbyte),
2504 "D" (dstbits),
2505 "c" (dstwidth),
2506 "d" (colors)
2507 :"eax", "cc", "memory"
2509 srcbyte = (srcbits += linebytes);
2510 dstbits -= bmpImage->bytes_per_line;
2512 return;
2514 break;
2515 #endif
2516 case 24:
2517 case 32:
2518 #if defined(__i386__) && defined(__GNUC__)
2519 if (lines && dstwidth && (bmpImage->bits_per_pixel == 32) &&
2520 (ImageByteOrder(gdi_display)==LSBFirst) )
2522 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
2523 /* FIXME: Does this really handle both cases correctly? */
2524 /* ==== pal 8 dib -> rgb or bgr 0888 bmp ==== */
2525 for (h = lines ; h--; ) {
2526 int _cl1,_cl2; /* temp outputs for asm below */
2527 /* Borrowed from DirectDraw */
2528 __asm__ __volatile__(
2529 "xor %%eax,%%eax\n"
2530 "cld\n"
2531 "1:\n"
2532 " lodsb\n"
2533 " movl (%%edx,%%eax,4),%%eax\n"
2534 " stosl\n"
2535 " xor %%eax,%%eax\n"
2536 " loop 1b\n"
2537 :"=S" (srcbyte), "=D" (_cl1), "=c" (_cl2)
2538 :"S" (srcbyte),
2539 "D" (dstbits),
2540 "c" (dstwidth),
2541 "d" (colors)
2542 :"eax", "cc", "memory"
2544 srcbyte = (srcbits += linebytes);
2545 dstbits -= bmpImage->bytes_per_line;
2547 return;
2549 break;
2550 #endif
2551 default:
2552 break; /* use slow generic case below */
2555 /* ==== pal 8 dib -> any bmp format ==== */
2556 for (h=lines-1; h>=0; h--) {
2557 for (x=left; x<dstwidth+left; x++) {
2558 XPutPixel(bmpImage, x, h, colors[*srcbyte++]);
2560 srcbyte = (srcbits += linebytes);
2564 /***********************************************************************
2565 * X11DRV_DIB_GetImageBits_8
2567 * GetDIBits for an 8-bit deep DIB.
2569 static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
2570 DWORD srcwidth, DWORD dstwidth,
2571 RGBQUAD *colors, PALETTEENTRY *srccolors,
2572 XImage *bmpImage, DWORD linebytes )
2574 DWORD x;
2575 int h;
2576 BYTE* dstbyte;
2578 if (lines < 0 )
2580 lines = -lines;
2581 dstbits = dstbits + ( linebytes * (lines-1) );
2582 linebytes = -linebytes;
2586 * Hack for now
2587 * This condition is true when GetImageBits has been called by
2588 * UpdateDIBSection. For now, GetNearestIndex is too slow to support
2589 * 256 colormaps, so we'll just use for for GetDIBits calls.
2590 * (In somes cases, in a updateDIBSection, the returned colors are bad too)
2592 if (!srccolors) goto updatesection;
2594 switch (bmpImage->depth) {
2595 case 1:
2596 case 4:
2597 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2599 /* ==== pal 1 bmp -> pal 8 dib ==== */
2600 /* ==== pal 4 bmp -> pal 8 dib ==== */
2601 for (h=lines-1; h>=0; h--) {
2602 dstbyte=dstbits;
2603 for (x=0; x<dstwidth; x++) {
2604 PALETTEENTRY srcval;
2605 srcval=srccolors[XGetPixel(bmpImage, x, h)];
2606 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2607 srcval.peRed,
2608 srcval.peGreen,
2609 srcval.peBlue);
2611 dstbits += linebytes;
2613 } else {
2614 goto notsupported;
2616 break;
2618 case 8:
2619 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
2620 /* ==== pal 8 bmp -> pal 8 dib ==== */
2621 const void* srcbits;
2622 const BYTE* srcpixel;
2624 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2625 for (h=0; h<lines; h++) {
2626 srcpixel=srcbits;
2627 dstbyte=dstbits;
2628 for (x = 0; x < dstwidth; x++) {
2629 PALETTEENTRY srcval;
2630 srcval=srccolors[(int)*srcpixel++];
2631 *dstbyte++=X11DRV_DIB_GetNearestIndex(colors, 256,
2632 srcval.peRed,
2633 srcval.peGreen,
2634 srcval.peBlue);
2636 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2637 dstbits += linebytes;
2639 } else {
2640 goto notsupported;
2642 break;
2644 case 15:
2645 case 16:
2647 const void* srcbits;
2648 const WORD* srcpixel;
2649 BYTE* dstbyte;
2651 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2653 if (bmpImage->green_mask==0x03e0) {
2654 if (bmpImage->red_mask==0x7c00) {
2655 /* ==== rgb 555 bmp -> pal 8 dib ==== */
2656 for (h=0; h<lines; h++) {
2657 srcpixel=srcbits;
2658 dstbyte=dstbits;
2659 for (x=0; x<dstwidth; x++) {
2660 WORD srcval;
2661 srcval=*srcpixel++;
2662 *dstbyte++=X11DRV_DIB_GetNearestIndex
2663 (colors, 256,
2664 ((srcval >> 7) & 0xf8) | /* r */
2665 ((srcval >> 12) & 0x07),
2666 ((srcval >> 2) & 0xf8) | /* g */
2667 ((srcval >> 7) & 0x07),
2668 ((srcval << 3) & 0xf8) | /* b */
2669 ((srcval >> 2) & 0x07) );
2671 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2672 dstbits += linebytes;
2674 } else if (bmpImage->blue_mask==0x7c00) {
2675 /* ==== bgr 555 bmp -> pal 8 dib ==== */
2676 for (h=0; h<lines; h++) {
2677 srcpixel=srcbits;
2678 dstbyte=dstbits;
2679 for (x=0; x<dstwidth; x++) {
2680 WORD srcval;
2681 srcval=*srcpixel++;
2682 *dstbyte++=X11DRV_DIB_GetNearestIndex
2683 (colors, 256,
2684 ((srcval << 3) & 0xf8) | /* r */
2685 ((srcval >> 2) & 0x07),
2686 ((srcval >> 2) & 0xf8) | /* g */
2687 ((srcval >> 7) & 0x07),
2688 ((srcval >> 7) & 0xf8) | /* b */
2689 ((srcval >> 12) & 0x07) );
2691 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2692 dstbits += linebytes;
2694 } else {
2695 goto notsupported;
2697 } else if (bmpImage->green_mask==0x07e0) {
2698 if (bmpImage->red_mask==0xf800) {
2699 /* ==== rgb 565 bmp -> pal 8 dib ==== */
2700 for (h=0; h<lines; h++) {
2701 srcpixel=srcbits;
2702 dstbyte=dstbits;
2703 for (x=0; x<dstwidth; x++) {
2704 WORD srcval;
2705 srcval=*srcpixel++;
2706 *dstbyte++=X11DRV_DIB_GetNearestIndex
2707 (colors, 256,
2708 ((srcval >> 8) & 0xf8) | /* r */
2709 ((srcval >> 13) & 0x07),
2710 ((srcval >> 3) & 0xfc) | /* g */
2711 ((srcval >> 9) & 0x03),
2712 ((srcval << 3) & 0xf8) | /* b */
2713 ((srcval >> 2) & 0x07) );
2715 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2716 dstbits += linebytes;
2718 } else if (bmpImage->blue_mask==0xf800) {
2719 /* ==== bgr 565 bmp -> pal 8 dib ==== */
2720 for (h=0; h<lines; h++) {
2721 srcpixel=srcbits;
2722 dstbyte=dstbits;
2723 for (x=0; x<dstwidth; x++) {
2724 WORD srcval;
2725 srcval=*srcpixel++;
2726 *dstbyte++=X11DRV_DIB_GetNearestIndex
2727 (colors, 256,
2728 ((srcval << 3) & 0xf8) | /* r */
2729 ((srcval >> 2) & 0x07),
2730 ((srcval >> 3) & 0xfc) | /* g */
2731 ((srcval >> 9) & 0x03),
2732 ((srcval >> 8) & 0xf8) | /* b */
2733 ((srcval >> 13) & 0x07) );
2735 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2736 dstbits += linebytes;
2738 } else {
2739 goto notsupported;
2741 } else {
2742 goto notsupported;
2745 break;
2747 case 24:
2748 case 32:
2750 const void* srcbits;
2751 const BYTE *srcbyte;
2752 BYTE* dstbyte;
2753 int bytes_per_pixel;
2755 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
2756 bytes_per_pixel=(bmpImage->bits_per_pixel==24?3:4);
2758 if (bmpImage->green_mask!=0x00ff00 ||
2759 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
2760 goto notsupported;
2761 } else if (bmpImage->blue_mask==0xff) {
2762 /* ==== rgb 888 or 0888 bmp -> pal 8 dib ==== */
2763 for (h=0; h<lines; h++) {
2764 srcbyte=srcbits;
2765 dstbyte=dstbits;
2766 for (x=0; x<dstwidth; x++) {
2767 *dstbyte++=X11DRV_DIB_GetNearestIndex
2768 (colors, 256,
2769 srcbyte[2],
2770 srcbyte[1],
2771 srcbyte[0]);
2772 srcbyte+=bytes_per_pixel;
2774 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2775 dstbits += linebytes;
2777 } else {
2778 /* ==== bgr 888 or 0888 bmp -> pal 8 dib ==== */
2779 for (h=0; h<lines; h++) {
2780 srcbyte=srcbits;
2781 dstbyte=dstbits;
2782 for (x=0; x<dstwidth; x++) {
2783 *dstbyte++=X11DRV_DIB_GetNearestIndex
2784 (colors, 256,
2785 srcbyte[0],
2786 srcbyte[1],
2787 srcbyte[2]);
2788 srcbyte+=bytes_per_pixel;
2790 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
2791 dstbits += linebytes;
2795 break;
2797 default:
2798 notsupported:
2799 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 8 bit DIB\n",
2800 bmpImage->depth, bmpImage->red_mask,
2801 bmpImage->green_mask, bmpImage->blue_mask );
2802 updatesection:
2803 /* ==== any bmp format -> pal 8 dib ==== */
2804 for (h=lines-1; h>=0; h--) {
2805 dstbyte=dstbits;
2806 for (x=0; x<dstwidth; x++) {
2807 *dstbyte=X11DRV_DIB_MapColor
2808 ((int*)colors, 256,
2809 XGetPixel(bmpImage, x, h), *dstbyte);
2810 dstbyte++;
2812 dstbits += linebytes;
2814 break;
2818 /***********************************************************************
2819 * X11DRV_DIB_SetImageBits_RLE8
2821 * SetDIBits for an 8-bit deep compressed DIB.
2823 * This function rewritten 941113 by James Youngman. WINE blew out when I
2824 * first ran it because my desktop wallpaper is a (large) RLE8 bitmap.
2826 * This was because the algorithm assumed that all RLE8 bitmaps end with the
2827 * 'End of bitmap' escape code. This code is very much laxer in what it
2828 * allows to end the expansion. Possibly too lax. See the note by
2829 * case RleDelta. BTW, MS's documentation implies that a correct RLE8
2830 * bitmap should end with RleEnd, but on the other hand, software exists
2831 * that produces ones that don't and Windows 3.1 doesn't complain a bit
2832 * about it.
2834 * (No) apologies for my English spelling. [Emacs users: c-indent-level=4].
2835 * James A. Youngman <mbcstjy@afs.man.ac.uk>
2836 * [JAY]
2838 static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
2839 DWORD width, DWORD dstwidth,
2840 int left, int *colors,
2841 XImage *bmpImage )
2843 int x; /* X-positon on each line. Increases. */
2844 int y; /* Line #. Starts at lines-1, decreases */
2845 const BYTE *pIn = bits; /* Pointer to current position in bits */
2846 BYTE length; /* The length pf a run */
2847 BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
2850 * Note that the bitmap data is stored by Windows starting at the
2851 * bottom line of the bitmap and going upwards. Within each line,
2852 * the data is stored left-to-right. That's the reason why line
2853 * goes from lines-1 to 0. [JAY]
2856 x = 0;
2857 y = lines - 1;
2858 while (y >= 0)
2860 length = *pIn++;
2863 * If the length byte is not zero (which is the escape value),
2864 * We have a run of length pixels all the same colour. The colour
2865 * index is stored next.
2867 * If the length byte is zero, we need to read the next byte to
2868 * know what to do. [JAY]
2870 if (length != 0)
2873 * [Run-Length] Encoded mode
2875 int color = colors[*pIn++];
2876 while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
2878 else
2881 * Escape codes (may be an absolute sequence though)
2883 escape_code = (*pIn++);
2884 switch(escape_code)
2886 case RLE_EOL:
2887 x = 0;
2888 y--;
2889 break;
2891 case RLE_END:
2892 /* Not all RLE8 bitmaps end with this code. For
2893 * example, Paint Shop Pro produces some that don't.
2894 * That's (I think) what caused the previous
2895 * implementation to fail. [JAY]
2897 return;
2899 case RLE_DELTA:
2900 x += (*pIn++);
2901 y -= (*pIn++);
2902 break;
2904 default: /* switch to absolute mode */
2905 length = escape_code;
2906 while (length--)
2908 int color = colors[*pIn++];
2909 if (x >= dstwidth)
2911 pIn += length;
2912 break;
2914 XPutPixel(bmpImage, x++, y, color);
2917 * If you think for a moment you'll realise that the
2918 * only time we could ever possibly read an odd
2919 * number of bytes is when there is a 0x00 (escape),
2920 * a value >0x02 (absolute mode) and then an odd-
2921 * length run. Therefore this is the only place we
2922 * need to worry about it. Everywhere else the
2923 * bytes are always read in pairs. [JAY]
2925 if (escape_code & 1) pIn++; /* Throw away the pad byte. */
2926 break;
2927 } /* switch (escape_code) : Escape sequence */
2933 /***********************************************************************
2934 * X11DRV_DIB_SetImageBits_16
2936 * SetDIBits for a 16-bit deep DIB.
2938 static void X11DRV_DIB_SetImageBits_16( int lines, const BYTE *srcbits,
2939 DWORD srcwidth, DWORD dstwidth, int left,
2940 X11DRV_PDEVICE *physDev, DWORD rSrc, DWORD gSrc, DWORD bSrc,
2941 XImage *bmpImage, DWORD linebytes )
2943 DWORD x;
2944 int h;
2946 if (lines < 0 )
2948 lines = -lines;
2949 srcbits = srcbits + ( linebytes * (lines-1));
2950 linebytes = -linebytes;
2953 switch (bmpImage->depth)
2955 case 15:
2956 case 16:
2958 char* dstbits;
2960 srcbits=srcbits+left*2;
2961 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
2963 if (bmpImage->green_mask==0x03e0) {
2964 if (gSrc==bmpImage->green_mask) {
2965 if (rSrc==bmpImage->red_mask) {
2966 /* ==== rgb 555 dib -> rgb 555 bmp ==== */
2967 /* ==== bgr 555 dib -> bgr 555 bmp ==== */
2968 X11DRV_DIB_Convert_any_asis
2969 (dstwidth,lines,2,
2970 srcbits,linebytes,
2971 dstbits,-bmpImage->bytes_per_line);
2972 } else if (rSrc==bmpImage->blue_mask) {
2973 /* ==== rgb 555 dib -> bgr 555 bmp ==== */
2974 /* ==== bgr 555 dib -> rgb 555 bmp ==== */
2975 X11DRV_DIB_Convert_555_reverse
2976 (dstwidth,lines,
2977 srcbits,linebytes,
2978 dstbits,-bmpImage->bytes_per_line);
2980 } else {
2981 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
2982 /* ==== rgb 565 dib -> rgb 555 bmp ==== */
2983 /* ==== bgr 565 dib -> bgr 555 bmp ==== */
2984 X11DRV_DIB_Convert_565_to_555_asis
2985 (dstwidth,lines,
2986 srcbits,linebytes,
2987 dstbits,-bmpImage->bytes_per_line);
2988 } else {
2989 /* ==== rgb 565 dib -> bgr 555 bmp ==== */
2990 /* ==== bgr 565 dib -> rgb 555 bmp ==== */
2991 X11DRV_DIB_Convert_565_to_555_reverse
2992 (dstwidth,lines,
2993 srcbits,linebytes,
2994 dstbits,-bmpImage->bytes_per_line);
2997 } else if (bmpImage->green_mask==0x07e0) {
2998 if (gSrc==bmpImage->green_mask) {
2999 if (rSrc==bmpImage->red_mask) {
3000 /* ==== rgb 565 dib -> rgb 565 bmp ==== */
3001 /* ==== bgr 565 dib -> bgr 565 bmp ==== */
3002 X11DRV_DIB_Convert_any_asis
3003 (dstwidth,lines,2,
3004 srcbits,linebytes,
3005 dstbits,-bmpImage->bytes_per_line);
3006 } else {
3007 /* ==== rgb 565 dib -> bgr 565 bmp ==== */
3008 /* ==== bgr 565 dib -> rgb 565 bmp ==== */
3009 X11DRV_DIB_Convert_565_reverse
3010 (dstwidth,lines,
3011 srcbits,linebytes,
3012 dstbits,-bmpImage->bytes_per_line);
3014 } else {
3015 if (rSrc==bmpImage->red_mask || bSrc==bmpImage->blue_mask) {
3016 /* ==== rgb 555 dib -> rgb 565 bmp ==== */
3017 /* ==== bgr 555 dib -> bgr 565 bmp ==== */
3018 X11DRV_DIB_Convert_555_to_565_asis
3019 (dstwidth,lines,
3020 srcbits,linebytes,
3021 dstbits,-bmpImage->bytes_per_line);
3022 } else {
3023 /* ==== rgb 555 dib -> bgr 565 bmp ==== */
3024 /* ==== bgr 555 dib -> rgb 565 bmp ==== */
3025 X11DRV_DIB_Convert_555_to_565_reverse
3026 (dstwidth,lines,
3027 srcbits,linebytes,
3028 dstbits,-bmpImage->bytes_per_line);
3031 } else {
3032 goto notsupported;
3035 break;
3037 case 24:
3038 if (bmpImage->bits_per_pixel==24) {
3039 char* dstbits;
3041 srcbits=srcbits+left*2;
3042 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3044 if (bmpImage->green_mask!=0x00ff00 ||
3045 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3046 goto notsupported;
3047 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3048 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3049 if (gSrc==0x03e0) {
3050 /* ==== rgb 555 dib -> rgb 888 bmp ==== */
3051 /* ==== bgr 555 dib -> bgr 888 bmp ==== */
3052 X11DRV_DIB_Convert_555_to_888_asis
3053 (dstwidth,lines,
3054 srcbits,linebytes,
3055 dstbits,-bmpImage->bytes_per_line);
3056 } else {
3057 /* ==== rgb 565 dib -> rgb 888 bmp ==== */
3058 /* ==== bgr 565 dib -> bgr 888 bmp ==== */
3059 X11DRV_DIB_Convert_565_to_888_asis
3060 (dstwidth,lines,
3061 srcbits,linebytes,
3062 dstbits,-bmpImage->bytes_per_line);
3064 } else {
3065 if (gSrc==0x03e0) {
3066 /* ==== rgb 555 dib -> bgr 888 bmp ==== */
3067 /* ==== bgr 555 dib -> rgb 888 bmp ==== */
3068 X11DRV_DIB_Convert_555_to_888_reverse
3069 (dstwidth,lines,
3070 srcbits,linebytes,
3071 dstbits,-bmpImage->bytes_per_line);
3072 } else {
3073 /* ==== rgb 565 dib -> bgr 888 bmp ==== */
3074 /* ==== bgr 565 dib -> rgb 888 bmp ==== */
3075 X11DRV_DIB_Convert_565_to_888_reverse
3076 (dstwidth,lines,
3077 srcbits,linebytes,
3078 dstbits,-bmpImage->bytes_per_line);
3081 break;
3083 /* Fall through */
3085 case 32:
3087 char* dstbits;
3089 srcbits=srcbits+left*2;
3090 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3092 if (bmpImage->green_mask!=0x00ff00 ||
3093 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3094 goto notsupported;
3095 } else if ((rSrc==0x1f && bmpImage->red_mask==0xff) ||
3096 (bSrc==0x1f && bmpImage->blue_mask==0xff)) {
3097 if (gSrc==0x03e0) {
3098 /* ==== rgb 555 dib -> rgb 0888 bmp ==== */
3099 /* ==== bgr 555 dib -> bgr 0888 bmp ==== */
3100 X11DRV_DIB_Convert_555_to_0888_asis
3101 (dstwidth,lines,
3102 srcbits,linebytes,
3103 dstbits,-bmpImage->bytes_per_line);
3104 } else {
3105 /* ==== rgb 565 dib -> rgb 0888 bmp ==== */
3106 /* ==== bgr 565 dib -> bgr 0888 bmp ==== */
3107 X11DRV_DIB_Convert_565_to_0888_asis
3108 (dstwidth,lines,
3109 srcbits,linebytes,
3110 dstbits,-bmpImage->bytes_per_line);
3112 } else {
3113 if (gSrc==0x03e0) {
3114 /* ==== rgb 555 dib -> bgr 0888 bmp ==== */
3115 /* ==== bgr 555 dib -> rgb 0888 bmp ==== */
3116 X11DRV_DIB_Convert_555_to_0888_reverse
3117 (dstwidth,lines,
3118 srcbits,linebytes,
3119 dstbits,-bmpImage->bytes_per_line);
3120 } else {
3121 /* ==== rgb 565 dib -> bgr 0888 bmp ==== */
3122 /* ==== bgr 565 dib -> rgb 0888 bmp ==== */
3123 X11DRV_DIB_Convert_565_to_0888_reverse
3124 (dstwidth,lines,
3125 srcbits,linebytes,
3126 dstbits,-bmpImage->bytes_per_line);
3130 break;
3132 default:
3133 notsupported:
3134 WARN("from 16 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3135 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3136 bmpImage->green_mask, bmpImage->blue_mask );
3137 /* fall through */
3138 case 1:
3139 case 4:
3140 case 8:
3142 /* ==== rgb or bgr 555 or 565 dib -> pal 1, 4 or 8 ==== */
3143 const WORD* srcpixel;
3144 int rShift1,gShift1,bShift1;
3145 int rShift2,gShift2,bShift2;
3146 BYTE gMask1,gMask2;
3148 /* Set color scaling values */
3149 rShift1=16+X11DRV_DIB_MaskToShift(rSrc)-3;
3150 gShift1=16+X11DRV_DIB_MaskToShift(gSrc)-3;
3151 bShift1=16+X11DRV_DIB_MaskToShift(bSrc)-3;
3152 rShift2=rShift1+5;
3153 gShift2=gShift1+5;
3154 bShift2=bShift1+5;
3155 if (gSrc==0x03e0) {
3156 /* Green has 5 bits, like the others */
3157 gMask1=0xf8;
3158 gMask2=0x07;
3159 } else {
3160 /* Green has 6 bits, not 5. Compensate. */
3161 gShift1++;
3162 gShift2+=2;
3163 gMask1=0xfc;
3164 gMask2=0x03;
3167 srcbits+=2*left;
3169 /* We could split it into four separate cases to optimize
3170 * but it is probably not worth it.
3172 for (h=lines-1; h>=0; h--) {
3173 srcpixel=(const WORD*)srcbits;
3174 for (x=left; x<dstwidth+left; x++) {
3175 DWORD srcval;
3176 BYTE red,green,blue;
3177 srcval=*srcpixel++ << 16;
3178 red= ((srcval >> rShift1) & 0xf8) |
3179 ((srcval >> rShift2) & 0x07);
3180 green=((srcval >> gShift1) & gMask1) |
3181 ((srcval >> gShift2) & gMask2);
3182 blue= ((srcval >> bShift1) & 0xf8) |
3183 ((srcval >> bShift2) & 0x07);
3184 XPutPixel(bmpImage, x, h,
3185 X11DRV_PALETTE_ToPhysical
3186 (physDev, RGB(red,green,blue)));
3188 srcbits += linebytes;
3191 break;
3196 /***********************************************************************
3197 * X11DRV_DIB_GetImageBits_16
3199 * GetDIBits for an 16-bit deep DIB.
3201 static void X11DRV_DIB_GetImageBits_16( int lines, BYTE *dstbits,
3202 DWORD dstwidth, DWORD srcwidth,
3203 PALETTEENTRY *srccolors,
3204 DWORD rDst, DWORD gDst, DWORD bDst,
3205 XImage *bmpImage, DWORD dibpitch )
3207 DWORD x;
3208 int h;
3210 DWORD linebytes = dibpitch;
3212 if (lines < 0 )
3214 lines = -lines;
3215 dstbits = dstbits + ( linebytes * (lines-1));
3216 linebytes = -linebytes;
3219 switch (bmpImage->depth)
3221 case 15:
3222 case 16:
3224 const char* srcbits;
3226 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3228 if (bmpImage->green_mask==0x03e0) {
3229 if (gDst==bmpImage->green_mask) {
3230 if (rDst==bmpImage->red_mask) {
3231 /* ==== rgb 555 bmp -> rgb 555 dib ==== */
3232 /* ==== bgr 555 bmp -> bgr 555 dib ==== */
3233 X11DRV_DIB_Convert_any_asis
3234 (dstwidth,lines,2,
3235 srcbits,-bmpImage->bytes_per_line,
3236 dstbits,linebytes);
3237 } else {
3238 /* ==== rgb 555 bmp -> bgr 555 dib ==== */
3239 /* ==== bgr 555 bmp -> rgb 555 dib ==== */
3240 X11DRV_DIB_Convert_555_reverse
3241 (dstwidth,lines,
3242 srcbits,-bmpImage->bytes_per_line,
3243 dstbits,linebytes);
3245 } else {
3246 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3247 /* ==== rgb 555 bmp -> rgb 565 dib ==== */
3248 /* ==== bgr 555 bmp -> bgr 565 dib ==== */
3249 X11DRV_DIB_Convert_555_to_565_asis
3250 (dstwidth,lines,
3251 srcbits,-bmpImage->bytes_per_line,
3252 dstbits,linebytes);
3253 } else {
3254 /* ==== rgb 555 bmp -> bgr 565 dib ==== */
3255 /* ==== bgr 555 bmp -> rgb 565 dib ==== */
3256 X11DRV_DIB_Convert_555_to_565_reverse
3257 (dstwidth,lines,
3258 srcbits,-bmpImage->bytes_per_line,
3259 dstbits,linebytes);
3262 } else if (bmpImage->green_mask==0x07e0) {
3263 if (gDst==bmpImage->green_mask) {
3264 if (rDst == bmpImage->red_mask) {
3265 /* ==== rgb 565 bmp -> rgb 565 dib ==== */
3266 /* ==== bgr 565 bmp -> bgr 565 dib ==== */
3267 X11DRV_DIB_Convert_any_asis
3268 (dstwidth,lines,2,
3269 srcbits,-bmpImage->bytes_per_line,
3270 dstbits,linebytes);
3271 } else {
3272 /* ==== rgb 565 bmp -> bgr 565 dib ==== */
3273 /* ==== bgr 565 bmp -> rgb 565 dib ==== */
3274 X11DRV_DIB_Convert_565_reverse
3275 (dstwidth,lines,
3276 srcbits,-bmpImage->bytes_per_line,
3277 dstbits,linebytes);
3279 } else {
3280 if (rDst==bmpImage->red_mask || bDst==bmpImage->blue_mask) {
3281 /* ==== rgb 565 bmp -> rgb 555 dib ==== */
3282 /* ==== bgr 565 bmp -> bgr 555 dib ==== */
3283 X11DRV_DIB_Convert_565_to_555_asis
3284 (dstwidth,lines,
3285 srcbits,-bmpImage->bytes_per_line,
3286 dstbits,linebytes);
3287 } else {
3288 /* ==== rgb 565 bmp -> bgr 555 dib ==== */
3289 /* ==== bgr 565 bmp -> rgb 555 dib ==== */
3290 X11DRV_DIB_Convert_565_to_555_reverse
3291 (dstwidth,lines,
3292 srcbits,-bmpImage->bytes_per_line,
3293 dstbits,linebytes);
3296 } else {
3297 goto notsupported;
3300 break;
3302 case 24:
3303 if (bmpImage->bits_per_pixel == 24) {
3304 const char* srcbits;
3306 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3308 if (bmpImage->green_mask!=0x00ff00 ||
3309 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3310 goto notsupported;
3311 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3312 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3313 if (gDst==0x03e0) {
3314 /* ==== rgb 888 bmp -> rgb 555 dib ==== */
3315 /* ==== bgr 888 bmp -> bgr 555 dib ==== */
3316 X11DRV_DIB_Convert_888_to_555_asis
3317 (dstwidth,lines,
3318 srcbits,-bmpImage->bytes_per_line,
3319 dstbits,linebytes);
3320 } else {
3321 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3322 /* ==== rgb 888 bmp -> rgb 565 dib ==== */
3323 X11DRV_DIB_Convert_888_to_565_asis
3324 (dstwidth,lines,
3325 srcbits,-bmpImage->bytes_per_line,
3326 dstbits,linebytes);
3328 } else {
3329 if (gDst==0x03e0) {
3330 /* ==== rgb 888 bmp -> bgr 555 dib ==== */
3331 /* ==== bgr 888 bmp -> rgb 555 dib ==== */
3332 X11DRV_DIB_Convert_888_to_555_reverse
3333 (dstwidth,lines,
3334 srcbits,-bmpImage->bytes_per_line,
3335 dstbits,linebytes);
3336 } else {
3337 /* ==== rgb 888 bmp -> bgr 565 dib ==== */
3338 /* ==== bgr 888 bmp -> rgb 565 dib ==== */
3339 X11DRV_DIB_Convert_888_to_565_reverse
3340 (dstwidth,lines,
3341 srcbits,-bmpImage->bytes_per_line,
3342 dstbits,linebytes);
3345 break;
3347 /* Fall through */
3349 case 32:
3351 const char* srcbits;
3353 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3355 if (bmpImage->green_mask!=0x00ff00 ||
3356 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3357 goto notsupported;
3358 } else if ((rDst==0x1f && bmpImage->red_mask==0xff) ||
3359 (bDst==0x1f && bmpImage->blue_mask==0xff)) {
3360 if (gDst==0x03e0) {
3361 /* ==== rgb 0888 bmp -> rgb 555 dib ==== */
3362 /* ==== bgr 0888 bmp -> bgr 555 dib ==== */
3363 X11DRV_DIB_Convert_0888_to_555_asis
3364 (dstwidth,lines,
3365 srcbits,-bmpImage->bytes_per_line,
3366 dstbits,linebytes);
3367 } else {
3368 /* ==== rgb 0888 bmp -> rgb 565 dib ==== */
3369 /* ==== bgr 0888 bmp -> bgr 565 dib ==== */
3370 X11DRV_DIB_Convert_0888_to_565_asis
3371 (dstwidth,lines,
3372 srcbits,-bmpImage->bytes_per_line,
3373 dstbits,linebytes);
3375 } else {
3376 if (gDst==0x03e0) {
3377 /* ==== rgb 0888 bmp -> bgr 555 dib ==== */
3378 /* ==== bgr 0888 bmp -> rgb 555 dib ==== */
3379 X11DRV_DIB_Convert_0888_to_555_reverse
3380 (dstwidth,lines,
3381 srcbits,-bmpImage->bytes_per_line,
3382 dstbits,linebytes);
3383 } else {
3384 /* ==== rgb 0888 bmp -> bgr 565 dib ==== */
3385 /* ==== bgr 0888 bmp -> rgb 565 dib ==== */
3386 X11DRV_DIB_Convert_0888_to_565_reverse
3387 (dstwidth,lines,
3388 srcbits,-bmpImage->bytes_per_line,
3389 dstbits,linebytes);
3393 break;
3395 case 1:
3396 case 4:
3397 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3398 /* ==== pal 1 or 4 bmp -> rgb or bgr 555 or 565 dib ==== */
3399 int rShift,gShift,bShift;
3400 WORD* dstpixel;
3402 /* Shift everything 16 bits left so that all shifts are >0,
3403 * even for BGR DIBs. Then a single >> 16 will bring everything
3404 * back into place.
3406 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3407 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3408 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3409 if (gDst==0x07e0) {
3410 /* 6 bits for the green */
3411 gShift++;
3413 rDst=rDst << 16;
3414 gDst=gDst << 16;
3415 bDst=bDst << 16;
3416 for (h = lines - 1; h >= 0; h--) {
3417 dstpixel=(LPWORD)dstbits;
3418 for (x = 0; x < dstwidth; x++) {
3419 PALETTEENTRY srcval;
3420 DWORD dstval;
3421 srcval=srccolors[XGetPixel(bmpImage, x, h)];
3422 dstval=((srcval.peRed << rShift) & rDst) |
3423 ((srcval.peGreen << gShift) & gDst) |
3424 ((srcval.peBlue << bShift) & bDst);
3425 *dstpixel++=dstval >> 16;
3427 dstbits += linebytes;
3429 } else {
3430 goto notsupported;
3432 break;
3434 case 8:
3435 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3436 /* ==== pal 8 bmp -> rgb or bgr 555 or 565 dib ==== */
3437 int rShift,gShift,bShift;
3438 const BYTE* srcbits;
3439 const BYTE* srcpixel;
3440 WORD* dstpixel;
3442 /* Shift everything 16 bits left so that all shifts are >0,
3443 * even for BGR DIBs. Then a single >> 16 will bring everything
3444 * back into place.
3446 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3447 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3448 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3449 if (gDst==0x07e0) {
3450 /* 6 bits for the green */
3451 gShift++;
3453 rDst=rDst << 16;
3454 gDst=gDst << 16;
3455 bDst=bDst << 16;
3456 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3457 for (h=0; h<lines; h++) {
3458 srcpixel=srcbits;
3459 dstpixel=(LPWORD)dstbits;
3460 for (x = 0; x < dstwidth; x++) {
3461 PALETTEENTRY srcval;
3462 DWORD dstval;
3463 srcval=srccolors[(int)*srcpixel++];
3464 dstval=((srcval.peRed << rShift) & rDst) |
3465 ((srcval.peGreen << gShift) & gDst) |
3466 ((srcval.peBlue << bShift) & bDst);
3467 *dstpixel++=dstval >> 16;
3469 srcbits -= bmpImage->bytes_per_line;
3470 dstbits += linebytes;
3472 } else {
3473 goto notsupported;
3475 break;
3477 default:
3478 notsupported:
3480 /* ==== any bmp format -> rgb or bgr 555 or 565 dib ==== */
3481 int rShift,gShift,bShift;
3482 WORD* dstpixel;
3484 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 16 bit DIB (%lx,%lx,%lx)\n",
3485 bmpImage->depth, bmpImage->red_mask,
3486 bmpImage->green_mask, bmpImage->blue_mask,
3487 rDst, gDst, bDst);
3489 /* Shift everything 16 bits left so that all shifts are >0,
3490 * even for BGR DIBs. Then a single >> 16 will bring everything
3491 * back into place.
3493 rShift=16+X11DRV_DIB_MaskToShift(rDst)-3;
3494 gShift=16+X11DRV_DIB_MaskToShift(gDst)-3;
3495 bShift=16+X11DRV_DIB_MaskToShift(bDst)-3;
3496 if (gDst==0x07e0) {
3497 /* 6 bits for the green */
3498 gShift++;
3500 rDst=rDst << 16;
3501 gDst=gDst << 16;
3502 bDst=bDst << 16;
3503 for (h = lines - 1; h >= 0; h--) {
3504 dstpixel=(LPWORD)dstbits;
3505 for (x = 0; x < dstwidth; x++) {
3506 COLORREF srcval;
3507 DWORD dstval;
3508 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
3509 dstval=((GetRValue(srcval) << rShift) & rDst) |
3510 ((GetGValue(srcval) << gShift) & gDst) |
3511 ((GetBValue(srcval) << bShift) & bDst);
3512 *dstpixel++=dstval >> 16;
3514 dstbits += linebytes;
3517 break;
3522 /***********************************************************************
3523 * X11DRV_DIB_SetImageBits_24
3525 * SetDIBits for a 24-bit deep DIB.
3527 static void X11DRV_DIB_SetImageBits_24( int lines, const BYTE *srcbits,
3528 DWORD srcwidth, DWORD dstwidth, int left,
3529 X11DRV_PDEVICE *physDev,
3530 DWORD rSrc, DWORD gSrc, DWORD bSrc,
3531 XImage *bmpImage, DWORD linebytes )
3533 DWORD x;
3534 int h;
3536 if (lines < 0 )
3538 lines = -lines;
3539 srcbits = srcbits + linebytes * (lines - 1);
3540 linebytes = -linebytes;
3543 switch (bmpImage->depth)
3545 case 24:
3546 if (bmpImage->bits_per_pixel==24) {
3547 char* dstbits;
3549 srcbits=srcbits+left*3;
3550 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3552 if (bmpImage->green_mask!=0x00ff00 ||
3553 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3554 goto notsupported;
3555 } else if (rSrc==bmpImage->red_mask) {
3556 /* ==== rgb 888 dib -> rgb 888 bmp ==== */
3557 /* ==== bgr 888 dib -> bgr 888 bmp ==== */
3558 X11DRV_DIB_Convert_any_asis
3559 (dstwidth,lines,3,
3560 srcbits,linebytes,
3561 dstbits,-bmpImage->bytes_per_line);
3562 } else {
3563 /* ==== rgb 888 dib -> bgr 888 bmp ==== */
3564 /* ==== bgr 888 dib -> rgb 888 bmp ==== */
3565 X11DRV_DIB_Convert_888_reverse
3566 (dstwidth,lines,
3567 srcbits,linebytes,
3568 dstbits,-bmpImage->bytes_per_line);
3570 break;
3572 /* fall through */
3574 case 32:
3576 char* dstbits;
3578 srcbits=srcbits+left*3;
3579 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3581 if (bmpImage->green_mask!=0x00ff00 ||
3582 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3583 goto notsupported;
3584 } else if (rSrc==bmpImage->red_mask) {
3585 /* ==== rgb 888 dib -> rgb 0888 bmp ==== */
3586 /* ==== bgr 888 dib -> bgr 0888 bmp ==== */
3587 X11DRV_DIB_Convert_888_to_0888_asis
3588 (dstwidth,lines,
3589 srcbits,linebytes,
3590 dstbits,-bmpImage->bytes_per_line);
3591 } else {
3592 /* ==== rgb 888 dib -> bgr 0888 bmp ==== */
3593 /* ==== bgr 888 dib -> rgb 0888 bmp ==== */
3594 X11DRV_DIB_Convert_888_to_0888_reverse
3595 (dstwidth,lines,
3596 srcbits,linebytes,
3597 dstbits,-bmpImage->bytes_per_line);
3599 break;
3602 case 15:
3603 case 16:
3605 char* dstbits;
3607 srcbits=srcbits+left*3;
3608 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
3610 if (bmpImage->green_mask==0x03e0) {
3611 if ((rSrc==0xff0000 && bmpImage->red_mask==0x7f00) ||
3612 (bSrc==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3613 /* ==== rgb 888 dib -> rgb 555 bmp ==== */
3614 /* ==== bgr 888 dib -> bgr 555 bmp ==== */
3615 X11DRV_DIB_Convert_888_to_555_asis
3616 (dstwidth,lines,
3617 srcbits,linebytes,
3618 dstbits,-bmpImage->bytes_per_line);
3619 } else if ((rSrc==0xff && bmpImage->red_mask==0x7f00) ||
3620 (bSrc==0xff && bmpImage->blue_mask==0x7f00)) {
3621 /* ==== rgb 888 dib -> bgr 555 bmp ==== */
3622 /* ==== bgr 888 dib -> rgb 555 bmp ==== */
3623 X11DRV_DIB_Convert_888_to_555_reverse
3624 (dstwidth,lines,
3625 srcbits,linebytes,
3626 dstbits,-bmpImage->bytes_per_line);
3627 } else {
3628 goto notsupported;
3630 } else if (bmpImage->green_mask==0x07e0) {
3631 if ((rSrc==0xff0000 && bmpImage->red_mask==0xf800) ||
3632 (bSrc==0xff0000 && bmpImage->blue_mask==0xf800)) {
3633 /* ==== rgb 888 dib -> rgb 565 bmp ==== */
3634 /* ==== bgr 888 dib -> bgr 565 bmp ==== */
3635 X11DRV_DIB_Convert_888_to_565_asis
3636 (dstwidth,lines,
3637 srcbits,linebytes,
3638 dstbits,-bmpImage->bytes_per_line);
3639 } else if ((rSrc==0xff && bmpImage->red_mask==0xf800) ||
3640 (bSrc==0xff && bmpImage->blue_mask==0xf800)) {
3641 /* ==== rgb 888 dib -> bgr 565 bmp ==== */
3642 /* ==== bgr 888 dib -> rgb 565 bmp ==== */
3643 X11DRV_DIB_Convert_888_to_565_reverse
3644 (dstwidth,lines,
3645 srcbits,linebytes,
3646 dstbits,-bmpImage->bytes_per_line);
3647 } else {
3648 goto notsupported;
3650 } else {
3651 goto notsupported;
3654 break;
3656 default:
3657 notsupported:
3658 WARN("from 24 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
3659 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
3660 bmpImage->green_mask, bmpImage->blue_mask );
3661 /* fall through */
3662 case 1:
3663 case 4:
3664 case 8:
3666 /* ==== rgb 888 dib -> any bmp bormat ==== */
3667 const BYTE* srcbyte;
3669 /* Windows only supports one 24bpp DIB format: RGB888 */
3670 srcbits+=left*3;
3671 for (h = lines - 1; h >= 0; h--) {
3672 srcbyte=(const BYTE*)srcbits;
3673 for (x = left; x < dstwidth+left; x++) {
3674 XPutPixel(bmpImage, x, h,
3675 X11DRV_PALETTE_ToPhysical
3676 (physDev, RGB(srcbyte[2], srcbyte[1], srcbyte[0])));
3677 srcbyte+=3;
3679 srcbits += linebytes;
3682 break;
3687 /***********************************************************************
3688 * X11DRV_DIB_GetImageBits_24
3690 * GetDIBits for an 24-bit deep DIB.
3692 static void X11DRV_DIB_GetImageBits_24( int lines, BYTE *dstbits,
3693 DWORD dstwidth, DWORD srcwidth,
3694 PALETTEENTRY *srccolors,
3695 DWORD rDst, DWORD gDst, DWORD bDst,
3696 XImage *bmpImage, DWORD linebytes )
3698 DWORD x;
3699 int h;
3701 if (lines < 0 )
3703 lines = -lines;
3704 dstbits = dstbits + ( linebytes * (lines-1) );
3705 linebytes = -linebytes;
3708 switch (bmpImage->depth)
3710 case 24:
3711 if (bmpImage->bits_per_pixel==24) {
3712 const char* srcbits;
3714 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3716 if (bmpImage->green_mask!=0x00ff00 ||
3717 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3718 goto notsupported;
3719 } else if (rDst==bmpImage->red_mask) {
3720 /* ==== rgb 888 bmp -> rgb 888 dib ==== */
3721 /* ==== bgr 888 bmp -> bgr 888 dib ==== */
3722 X11DRV_DIB_Convert_any_asis
3723 (dstwidth,lines,3,
3724 srcbits,-bmpImage->bytes_per_line,
3725 dstbits,linebytes);
3726 } else {
3727 /* ==== rgb 888 bmp -> bgr 888 dib ==== */
3728 /* ==== bgr 888 bmp -> rgb 888 dib ==== */
3729 X11DRV_DIB_Convert_888_reverse
3730 (dstwidth,lines,
3731 srcbits,-bmpImage->bytes_per_line,
3732 dstbits,linebytes);
3734 break;
3736 /* fall through */
3738 case 32:
3740 const char* srcbits;
3742 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3744 if (bmpImage->green_mask!=0x00ff00 ||
3745 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3746 goto notsupported;
3747 } else if (rDst==bmpImage->red_mask) {
3748 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
3749 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
3750 X11DRV_DIB_Convert_0888_to_888_asis
3751 (dstwidth,lines,
3752 srcbits,-bmpImage->bytes_per_line,
3753 dstbits,linebytes);
3754 } else {
3755 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
3756 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
3757 X11DRV_DIB_Convert_0888_to_888_reverse
3758 (dstwidth,lines,
3759 srcbits,-bmpImage->bytes_per_line,
3760 dstbits,linebytes);
3762 break;
3765 case 15:
3766 case 16:
3768 const char* srcbits;
3770 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3772 if (bmpImage->green_mask==0x03e0) {
3773 if ((rDst==0xff0000 && bmpImage->red_mask==0x7f00) ||
3774 (bDst==0xff0000 && bmpImage->blue_mask==0x7f00)) {
3775 /* ==== rgb 555 bmp -> rgb 888 dib ==== */
3776 /* ==== bgr 555 bmp -> bgr 888 dib ==== */
3777 X11DRV_DIB_Convert_555_to_888_asis
3778 (dstwidth,lines,
3779 srcbits,-bmpImage->bytes_per_line,
3780 dstbits,linebytes);
3781 } else if ((rDst==0xff && bmpImage->red_mask==0x7f00) ||
3782 (bDst==0xff && bmpImage->blue_mask==0x7f00)) {
3783 /* ==== rgb 555 bmp -> bgr 888 dib ==== */
3784 /* ==== bgr 555 bmp -> rgb 888 dib ==== */
3785 X11DRV_DIB_Convert_555_to_888_reverse
3786 (dstwidth,lines,
3787 srcbits,-bmpImage->bytes_per_line,
3788 dstbits,linebytes);
3789 } else {
3790 goto notsupported;
3792 } else if (bmpImage->green_mask==0x07e0) {
3793 if ((rDst==0xff0000 && bmpImage->red_mask==0xf800) ||
3794 (bDst==0xff0000 && bmpImage->blue_mask==0xf800)) {
3795 /* ==== rgb 565 bmp -> rgb 888 dib ==== */
3796 /* ==== bgr 565 bmp -> bgr 888 dib ==== */
3797 X11DRV_DIB_Convert_565_to_888_asis
3798 (dstwidth,lines,
3799 srcbits,-bmpImage->bytes_per_line,
3800 dstbits,linebytes);
3801 } else if ((rDst==0xff && bmpImage->red_mask==0xf800) ||
3802 (bDst==0xff && bmpImage->blue_mask==0xf800)) {
3803 /* ==== rgb 565 bmp -> bgr 888 dib ==== */
3804 /* ==== bgr 565 bmp -> rgb 888 dib ==== */
3805 X11DRV_DIB_Convert_565_to_888_reverse
3806 (dstwidth,lines,
3807 srcbits,-bmpImage->bytes_per_line,
3808 dstbits,linebytes);
3809 } else {
3810 goto notsupported;
3812 } else {
3813 goto notsupported;
3816 break;
3818 case 1:
3819 case 4:
3820 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
3821 /* ==== pal 1 or 4 bmp -> rgb 888 dib ==== */
3822 BYTE* dstbyte;
3824 /* Windows only supports one 24bpp DIB format: rgb 888 */
3825 for (h = lines - 1; h >= 0; h--) {
3826 dstbyte=dstbits;
3827 for (x = 0; x < dstwidth; x++) {
3828 PALETTEENTRY srcval;
3829 srcval=srccolors[XGetPixel(bmpImage, x, h)];
3830 dstbyte[0]=srcval.peBlue;
3831 dstbyte[1]=srcval.peGreen;
3832 dstbyte[2]=srcval.peRed;
3833 dstbyte+=3;
3835 dstbits += linebytes;
3837 } else {
3838 goto notsupported;
3840 break;
3842 case 8:
3843 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask == 0 && srccolors) {
3844 /* ==== pal 8 bmp -> rgb 888 dib ==== */
3845 const void* srcbits;
3846 const BYTE* srcpixel;
3847 BYTE* dstbyte;
3849 /* Windows only supports one 24bpp DIB format: rgb 888 */
3850 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
3851 for (h = lines - 1; h >= 0; h--) {
3852 srcpixel=srcbits;
3853 dstbyte=dstbits;
3854 for (x = 0; x < dstwidth; x++ ) {
3855 PALETTEENTRY srcval;
3856 srcval=srccolors[(int)*srcpixel++];
3857 dstbyte[0]=srcval.peBlue;
3858 dstbyte[1]=srcval.peGreen;
3859 dstbyte[2]=srcval.peRed;
3860 dstbyte+=3;
3862 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
3863 dstbits += linebytes;
3865 } else {
3866 goto notsupported;
3868 break;
3870 default:
3871 notsupported:
3873 /* ==== any bmp format -> 888 dib ==== */
3874 BYTE* dstbyte;
3876 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 24 bit DIB (%lx,%lx,%lx)\n",
3877 bmpImage->depth, bmpImage->red_mask,
3878 bmpImage->green_mask, bmpImage->blue_mask,
3879 rDst, gDst, bDst );
3881 /* Windows only supports one 24bpp DIB format: rgb 888 */
3882 for (h = lines - 1; h >= 0; h--) {
3883 dstbyte=dstbits;
3884 for (x = 0; x < dstwidth; x++) {
3885 COLORREF srcval=X11DRV_PALETTE_ToLogical
3886 (XGetPixel( bmpImage, x, h ));
3887 dstbyte[0]=GetBValue(srcval);
3888 dstbyte[1]=GetGValue(srcval);
3889 dstbyte[2]=GetRValue(srcval);
3890 dstbyte+=3;
3892 dstbits += linebytes;
3895 break;
3900 /***********************************************************************
3901 * X11DRV_DIB_SetImageBits_32
3903 * SetDIBits for a 32-bit deep DIB.
3905 static void X11DRV_DIB_SetImageBits_32(int lines, const BYTE *srcbits,
3906 DWORD srcwidth, DWORD dstwidth, int left,
3907 X11DRV_PDEVICE *physDev,
3908 DWORD rSrc, DWORD gSrc, DWORD bSrc,
3909 XImage *bmpImage,
3910 DWORD linebytes)
3912 DWORD x, *ptr;
3913 int h;
3915 if (lines < 0 )
3917 lines = -lines;
3918 srcbits = srcbits + ( linebytes * (lines-1) );
3919 linebytes = -linebytes;
3922 ptr = (DWORD *) srcbits + left;
3924 switch (bmpImage->depth)
3926 case 24:
3927 if (bmpImage->bits_per_pixel==24) {
3928 char* dstbits;
3930 srcbits=srcbits+left*4;
3931 dstbits=bmpImage->data+left*3+(lines-1)*bmpImage->bytes_per_line;
3933 if (rSrc==bmpImage->red_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->blue_mask) {
3934 /* ==== rgb 0888 dib -> rgb 888 bmp ==== */
3935 /* ==== bgr 0888 dib -> bgr 888 bmp ==== */
3936 X11DRV_DIB_Convert_0888_to_888_asis
3937 (dstwidth,lines,
3938 srcbits,linebytes,
3939 dstbits,-bmpImage->bytes_per_line);
3940 } else if (bmpImage->green_mask!=0x00ff00 ||
3941 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3942 goto notsupported;
3943 /* the tests below assume sane bmpImage masks */
3944 } else if (rSrc==bmpImage->blue_mask && gSrc==bmpImage->green_mask && bSrc==bmpImage->red_mask) {
3945 /* ==== rgb 0888 dib -> bgr 888 bmp ==== */
3946 /* ==== bgr 0888 dib -> rgb 888 bmp ==== */
3947 X11DRV_DIB_Convert_0888_to_888_reverse
3948 (dstwidth,lines,
3949 srcbits,linebytes,
3950 dstbits,-bmpImage->bytes_per_line);
3951 } else if (bmpImage->blue_mask==0xff) {
3952 /* ==== any 0888 dib -> rgb 888 bmp ==== */
3953 X11DRV_DIB_Convert_any0888_to_rgb888
3954 (dstwidth,lines,
3955 srcbits,linebytes,
3956 rSrc,gSrc,bSrc,
3957 dstbits,-bmpImage->bytes_per_line);
3958 } else {
3959 /* ==== any 0888 dib -> bgr 888 bmp ==== */
3960 X11DRV_DIB_Convert_any0888_to_bgr888
3961 (dstwidth,lines,
3962 srcbits,linebytes,
3963 rSrc,gSrc,bSrc,
3964 dstbits,-bmpImage->bytes_per_line);
3966 break;
3968 /* fall through */
3970 case 32:
3972 char* dstbits;
3974 srcbits=srcbits+left*4;
3975 dstbits=bmpImage->data+left*4+(lines-1)*bmpImage->bytes_per_line;
3977 if (gSrc==bmpImage->green_mask) {
3978 if (rSrc==bmpImage->red_mask && bSrc==bmpImage->blue_mask) {
3979 /* ==== rgb 0888 dib -> rgb 0888 bmp ==== */
3980 /* ==== bgr 0888 dib -> bgr 0888 bmp ==== */
3981 X11DRV_DIB_Convert_any_asis
3982 (dstwidth,lines,4,
3983 srcbits,linebytes,
3984 dstbits,-bmpImage->bytes_per_line);
3985 } else if (bmpImage->green_mask!=0x00ff00 ||
3986 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
3987 goto notsupported;
3988 /* the tests below assume sane bmpImage masks */
3989 } else if (rSrc==bmpImage->blue_mask && bSrc==bmpImage->red_mask) {
3990 /* ==== rgb 0888 dib -> bgr 0888 bmp ==== */
3991 /* ==== bgr 0888 dib -> rgb 0888 bmp ==== */
3992 X11DRV_DIB_Convert_0888_reverse
3993 (dstwidth,lines,
3994 srcbits,linebytes,
3995 dstbits,-bmpImage->bytes_per_line);
3996 } else {
3997 /* ==== any 0888 dib -> any 0888 bmp ==== */
3998 X11DRV_DIB_Convert_0888_any
3999 (dstwidth,lines,
4000 srcbits,linebytes,
4001 rSrc,gSrc,bSrc,
4002 dstbits,-bmpImage->bytes_per_line,
4003 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4005 } else if (bmpImage->green_mask!=0x00ff00 ||
4006 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4007 goto notsupported;
4008 /* the tests below assume sane bmpImage masks */
4009 } else {
4010 /* ==== any 0888 dib -> any 0888 bmp ==== */
4011 X11DRV_DIB_Convert_0888_any
4012 (dstwidth,lines,
4013 srcbits,linebytes,
4014 rSrc,gSrc,bSrc,
4015 dstbits,-bmpImage->bytes_per_line,
4016 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4019 break;
4021 case 15:
4022 case 16:
4024 char* dstbits;
4026 srcbits=srcbits+left*4;
4027 dstbits=bmpImage->data+left*2+(lines-1)*bmpImage->bytes_per_line;
4029 if (rSrc==0xff0000 && gSrc==0x00ff00 && bSrc==0x0000ff) {
4030 if (bmpImage->green_mask==0x03e0) {
4031 if (bmpImage->red_mask==0x7f00) {
4032 /* ==== rgb 0888 dib -> rgb 555 bmp ==== */
4033 X11DRV_DIB_Convert_0888_to_555_asis
4034 (dstwidth,lines,
4035 srcbits,linebytes,
4036 dstbits,-bmpImage->bytes_per_line);
4037 } else if (bmpImage->blue_mask==0x7f00) {
4038 /* ==== rgb 0888 dib -> bgr 555 bmp ==== */
4039 X11DRV_DIB_Convert_0888_to_555_reverse
4040 (dstwidth,lines,
4041 srcbits,linebytes,
4042 dstbits,-bmpImage->bytes_per_line);
4043 } else {
4044 goto notsupported;
4046 } else if (bmpImage->green_mask==0x07e0) {
4047 if (bmpImage->red_mask==0xf800) {
4048 /* ==== rgb 0888 dib -> rgb 565 bmp ==== */
4049 X11DRV_DIB_Convert_0888_to_565_asis
4050 (dstwidth,lines,
4051 srcbits,linebytes,
4052 dstbits,-bmpImage->bytes_per_line);
4053 } else if (bmpImage->blue_mask==0xf800) {
4054 /* ==== rgb 0888 dib -> bgr 565 bmp ==== */
4055 X11DRV_DIB_Convert_0888_to_565_reverse
4056 (dstwidth,lines,
4057 srcbits,linebytes,
4058 dstbits,-bmpImage->bytes_per_line);
4059 } else {
4060 goto notsupported;
4062 } else {
4063 goto notsupported;
4065 } else if (rSrc==0x0000ff && gSrc==0x00ff00 && bSrc==0xff0000) {
4066 if (bmpImage->green_mask==0x03e0) {
4067 if (bmpImage->blue_mask==0x7f00) {
4068 /* ==== bgr 0888 dib -> bgr 555 bmp ==== */
4069 X11DRV_DIB_Convert_0888_to_555_asis
4070 (dstwidth,lines,
4071 srcbits,linebytes,
4072 dstbits,-bmpImage->bytes_per_line);
4073 } else if (bmpImage->red_mask==0x7f00) {
4074 /* ==== bgr 0888 dib -> rgb 555 bmp ==== */
4075 X11DRV_DIB_Convert_0888_to_555_reverse
4076 (dstwidth,lines,
4077 srcbits,linebytes,
4078 dstbits,-bmpImage->bytes_per_line);
4079 } else {
4080 goto notsupported;
4082 } else if (bmpImage->green_mask==0x07e0) {
4083 if (bmpImage->blue_mask==0xf800) {
4084 /* ==== bgr 0888 dib -> bgr 565 bmp ==== */
4085 X11DRV_DIB_Convert_0888_to_565_asis
4086 (dstwidth,lines,
4087 srcbits,linebytes,
4088 dstbits,-bmpImage->bytes_per_line);
4089 } else if (bmpImage->red_mask==0xf800) {
4090 /* ==== bgr 0888 dib -> rgb 565 bmp ==== */
4091 X11DRV_DIB_Convert_0888_to_565_reverse
4092 (dstwidth,lines,
4093 srcbits,linebytes,
4094 dstbits,-bmpImage->bytes_per_line);
4095 } else {
4096 goto notsupported;
4098 } else {
4099 goto notsupported;
4101 } else {
4102 if (bmpImage->green_mask==0x03e0 &&
4103 (bmpImage->red_mask==0x7f00 ||
4104 bmpImage->blue_mask==0x7f00)) {
4105 /* ==== any 0888 dib -> rgb or bgr 555 bmp ==== */
4106 X11DRV_DIB_Convert_any0888_to_5x5
4107 (dstwidth,lines,
4108 srcbits,linebytes,
4109 rSrc,gSrc,bSrc,
4110 dstbits,-bmpImage->bytes_per_line,
4111 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4112 } else if (bmpImage->green_mask==0x07e0 &&
4113 (bmpImage->red_mask==0xf800 ||
4114 bmpImage->blue_mask==0xf800)) {
4115 /* ==== any 0888 dib -> rgb or bgr 565 bmp ==== */
4116 X11DRV_DIB_Convert_any0888_to_5x5
4117 (dstwidth,lines,
4118 srcbits,linebytes,
4119 rSrc,gSrc,bSrc,
4120 dstbits,-bmpImage->bytes_per_line,
4121 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4122 } else {
4123 goto notsupported;
4127 break;
4129 default:
4130 notsupported:
4131 WARN("from 32 bit DIB (%lx,%lx,%lx) to unknown %d bit bitmap (%lx,%lx,%lx)\n",
4132 rSrc, gSrc, bSrc, bmpImage->bits_per_pixel, bmpImage->red_mask,
4133 bmpImage->green_mask, bmpImage->blue_mask );
4134 /* fall through */
4135 case 1:
4136 case 4:
4137 case 8:
4139 /* ==== any 0888 dib -> pal 1, 4 or 8 bmp ==== */
4140 const DWORD* srcpixel;
4141 int rShift,gShift,bShift;
4143 rShift=X11DRV_DIB_MaskToShift(rSrc);
4144 gShift=X11DRV_DIB_MaskToShift(gSrc);
4145 bShift=X11DRV_DIB_MaskToShift(bSrc);
4146 srcbits+=left*4;
4147 for (h = lines - 1; h >= 0; h--) {
4148 srcpixel=(const DWORD*)srcbits;
4149 for (x = left; x < dstwidth+left; x++) {
4150 DWORD srcvalue;
4151 BYTE red,green,blue;
4152 srcvalue=*srcpixel++;
4153 red= (srcvalue >> rShift) & 0xff;
4154 green=(srcvalue >> gShift) & 0xff;
4155 blue= (srcvalue >> bShift) & 0xff;
4156 XPutPixel(bmpImage, x, h, X11DRV_PALETTE_ToPhysical
4157 (physDev, RGB(red,green,blue)));
4159 srcbits += linebytes;
4162 break;
4167 /***********************************************************************
4168 * X11DRV_DIB_GetImageBits_32
4170 * GetDIBits for an 32-bit deep DIB.
4172 static void X11DRV_DIB_GetImageBits_32( int lines, BYTE *dstbits,
4173 DWORD dstwidth, DWORD srcwidth,
4174 PALETTEENTRY *srccolors,
4175 DWORD rDst, DWORD gDst, DWORD bDst,
4176 XImage *bmpImage, DWORD linebytes )
4178 DWORD x;
4179 int h;
4180 BYTE *bits;
4182 if (lines < 0 )
4184 lines = -lines;
4185 dstbits = dstbits + ( linebytes * (lines-1) );
4186 linebytes = -linebytes;
4189 bits = dstbits;
4191 switch (bmpImage->depth)
4193 case 24:
4194 if (bmpImage->bits_per_pixel==24) {
4195 const void* srcbits;
4197 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4199 if (rDst==bmpImage->red_mask && gDst==bmpImage->green_mask && bDst==bmpImage->blue_mask) {
4200 /* ==== rgb 888 bmp -> rgb 0888 dib ==== */
4201 /* ==== bgr 888 bmp -> bgr 0888 dib ==== */
4202 X11DRV_DIB_Convert_888_to_0888_asis
4203 (dstwidth,lines,
4204 srcbits,-bmpImage->bytes_per_line,
4205 dstbits,linebytes);
4206 } else if (bmpImage->green_mask!=0x00ff00 ||
4207 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4208 goto notsupported;
4209 /* the tests below assume sane bmpImage masks */
4210 } else if (rDst==bmpImage->blue_mask && gDst==bmpImage->green_mask && bDst==bmpImage->red_mask) {
4211 /* ==== rgb 888 bmp -> bgr 0888 dib ==== */
4212 /* ==== bgr 888 bmp -> rgb 0888 dib ==== */
4213 X11DRV_DIB_Convert_888_to_0888_reverse
4214 (dstwidth,lines,
4215 srcbits,-bmpImage->bytes_per_line,
4216 dstbits,linebytes);
4217 } else if (bmpImage->blue_mask==0xff) {
4218 /* ==== rgb 888 bmp -> any 0888 dib ==== */
4219 X11DRV_DIB_Convert_rgb888_to_any0888
4220 (dstwidth,lines,
4221 srcbits,-bmpImage->bytes_per_line,
4222 dstbits,linebytes,
4223 rDst,gDst,bDst);
4224 } else {
4225 /* ==== bgr 888 bmp -> any 0888 dib ==== */
4226 X11DRV_DIB_Convert_bgr888_to_any0888
4227 (dstwidth,lines,
4228 srcbits,-bmpImage->bytes_per_line,
4229 dstbits,linebytes,
4230 rDst,gDst,bDst);
4232 break;
4234 /* fall through */
4236 case 32:
4238 const char* srcbits;
4240 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4242 if (gDst==bmpImage->green_mask) {
4243 if (rDst==bmpImage->red_mask && bDst==bmpImage->blue_mask) {
4244 /* ==== rgb 0888 bmp -> rgb 0888 dib ==== */
4245 /* ==== bgr 0888 bmp -> bgr 0888 dib ==== */
4246 X11DRV_DIB_Convert_any_asis
4247 (dstwidth,lines,4,
4248 srcbits,-bmpImage->bytes_per_line,
4249 dstbits,linebytes);
4250 } else if (bmpImage->green_mask!=0x00ff00 ||
4251 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4252 goto notsupported;
4253 /* the tests below assume sane bmpImage masks */
4254 } else if (rDst==bmpImage->blue_mask && bDst==bmpImage->red_mask) {
4255 /* ==== rgb 0888 bmp -> bgr 0888 dib ==== */
4256 /* ==== bgr 0888 bmp -> rgb 0888 dib ==== */
4257 X11DRV_DIB_Convert_0888_reverse
4258 (dstwidth,lines,
4259 srcbits,-bmpImage->bytes_per_line,
4260 dstbits,linebytes);
4261 } else {
4262 /* ==== any 0888 bmp -> any 0888 dib ==== */
4263 X11DRV_DIB_Convert_0888_any
4264 (dstwidth,lines,
4265 srcbits,-bmpImage->bytes_per_line,
4266 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4267 dstbits,linebytes,
4268 rDst,gDst,bDst);
4270 } else if (bmpImage->green_mask!=0x00ff00 ||
4271 (bmpImage->red_mask|bmpImage->blue_mask)!=0xff00ff) {
4272 goto notsupported;
4273 /* the tests below assume sane bmpImage masks */
4274 } else {
4275 /* ==== any 0888 bmp -> any 0888 dib ==== */
4276 X11DRV_DIB_Convert_0888_any
4277 (dstwidth,lines,
4278 srcbits,-bmpImage->bytes_per_line,
4279 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4280 dstbits,linebytes,
4281 rDst,gDst,bDst);
4284 break;
4286 case 15:
4287 case 16:
4289 const char* srcbits;
4291 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4293 if (rDst==0xff0000 && gDst==0x00ff00 && bDst==0x0000ff) {
4294 if (bmpImage->green_mask==0x03e0) {
4295 if (bmpImage->red_mask==0x7f00) {
4296 /* ==== rgb 555 bmp -> rgb 0888 dib ==== */
4297 X11DRV_DIB_Convert_555_to_0888_asis
4298 (dstwidth,lines,
4299 srcbits,-bmpImage->bytes_per_line,
4300 dstbits,linebytes);
4301 } else if (bmpImage->blue_mask==0x7f00) {
4302 /* ==== bgr 555 bmp -> rgb 0888 dib ==== */
4303 X11DRV_DIB_Convert_555_to_0888_reverse
4304 (dstwidth,lines,
4305 srcbits,-bmpImage->bytes_per_line,
4306 dstbits,linebytes);
4307 } else {
4308 goto notsupported;
4310 } else if (bmpImage->green_mask==0x07e0) {
4311 if (bmpImage->red_mask==0xf800) {
4312 /* ==== rgb 565 bmp -> rgb 0888 dib ==== */
4313 X11DRV_DIB_Convert_565_to_0888_asis
4314 (dstwidth,lines,
4315 srcbits,-bmpImage->bytes_per_line,
4316 dstbits,linebytes);
4317 } else if (bmpImage->blue_mask==0xf800) {
4318 /* ==== bgr 565 bmp -> rgb 0888 dib ==== */
4319 X11DRV_DIB_Convert_565_to_0888_reverse
4320 (dstwidth,lines,
4321 srcbits,-bmpImage->bytes_per_line,
4322 dstbits,linebytes);
4323 } else {
4324 goto notsupported;
4326 } else {
4327 goto notsupported;
4329 } else if (rDst==0x0000ff && gDst==0x00ff00 && bDst==0xff0000) {
4330 if (bmpImage->green_mask==0x03e0) {
4331 if (bmpImage->blue_mask==0x7f00) {
4332 /* ==== bgr 555 bmp -> bgr 0888 dib ==== */
4333 X11DRV_DIB_Convert_555_to_0888_asis
4334 (dstwidth,lines,
4335 srcbits,-bmpImage->bytes_per_line,
4336 dstbits,linebytes);
4337 } else if (bmpImage->red_mask==0x7f00) {
4338 /* ==== rgb 555 bmp -> bgr 0888 dib ==== */
4339 X11DRV_DIB_Convert_555_to_0888_reverse
4340 (dstwidth,lines,
4341 srcbits,-bmpImage->bytes_per_line,
4342 dstbits,linebytes);
4343 } else {
4344 goto notsupported;
4346 } else if (bmpImage->green_mask==0x07e0) {
4347 if (bmpImage->blue_mask==0xf800) {
4348 /* ==== bgr 565 bmp -> bgr 0888 dib ==== */
4349 X11DRV_DIB_Convert_565_to_0888_asis
4350 (dstwidth,lines,
4351 srcbits,-bmpImage->bytes_per_line,
4352 dstbits,linebytes);
4353 } else if (bmpImage->red_mask==0xf800) {
4354 /* ==== rgb 565 bmp -> bgr 0888 dib ==== */
4355 X11DRV_DIB_Convert_565_to_0888_reverse
4356 (dstwidth,lines,
4357 srcbits,-bmpImage->bytes_per_line,
4358 dstbits,linebytes);
4359 } else {
4360 goto notsupported;
4362 } else {
4363 goto notsupported;
4365 } else {
4366 if (bmpImage->green_mask==0x03e0 &&
4367 (bmpImage->red_mask==0x7f00 ||
4368 bmpImage->blue_mask==0x7f00)) {
4369 /* ==== rgb or bgr 555 bmp -> any 0888 dib ==== */
4370 X11DRV_DIB_Convert_5x5_to_any0888
4371 (dstwidth,lines,
4372 srcbits,-bmpImage->bytes_per_line,
4373 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4374 dstbits,linebytes,
4375 rDst,gDst,bDst);
4376 } else if (bmpImage->green_mask==0x07e0 &&
4377 (bmpImage->red_mask==0xf800 ||
4378 bmpImage->blue_mask==0xf800)) {
4379 /* ==== rgb or bgr 565 bmp -> any 0888 dib ==== */
4380 X11DRV_DIB_Convert_5x5_to_any0888
4381 (dstwidth,lines,
4382 srcbits,-bmpImage->bytes_per_line,
4383 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask,
4384 dstbits,linebytes,
4385 rDst,gDst,bDst);
4386 } else {
4387 goto notsupported;
4391 break;
4393 case 1:
4394 case 4:
4395 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4396 /* ==== pal 1 or 4 bmp -> any 0888 dib ==== */
4397 int rShift,gShift,bShift;
4398 DWORD* dstpixel;
4400 rShift=X11DRV_DIB_MaskToShift(rDst);
4401 gShift=X11DRV_DIB_MaskToShift(gDst);
4402 bShift=X11DRV_DIB_MaskToShift(bDst);
4403 for (h = lines - 1; h >= 0; h--) {
4404 dstpixel=(DWORD*)dstbits;
4405 for (x = 0; x < dstwidth; x++) {
4406 PALETTEENTRY srcval;
4407 srcval = srccolors[XGetPixel(bmpImage, x, h)];
4408 *dstpixel++=(srcval.peRed << rShift) |
4409 (srcval.peGreen << gShift) |
4410 (srcval.peBlue << bShift);
4412 dstbits += linebytes;
4414 } else {
4415 goto notsupported;
4417 break;
4419 case 8:
4420 if (bmpImage->red_mask==0 && bmpImage->green_mask==0 && bmpImage->blue_mask==0 && srccolors) {
4421 /* ==== pal 8 bmp -> any 0888 dib ==== */
4422 int rShift,gShift,bShift;
4423 const void* srcbits;
4424 const BYTE* srcpixel;
4425 DWORD* dstpixel;
4427 rShift=X11DRV_DIB_MaskToShift(rDst);
4428 gShift=X11DRV_DIB_MaskToShift(gDst);
4429 bShift=X11DRV_DIB_MaskToShift(bDst);
4430 srcbits=bmpImage->data+(lines-1)*bmpImage->bytes_per_line;
4431 for (h = lines - 1; h >= 0; h--) {
4432 srcpixel=srcbits;
4433 dstpixel=(DWORD*)dstbits;
4434 for (x = 0; x < dstwidth; x++) {
4435 PALETTEENTRY srcval;
4436 srcval=srccolors[(int)*srcpixel++];
4437 *dstpixel++=(srcval.peRed << rShift) |
4438 (srcval.peGreen << gShift) |
4439 (srcval.peBlue << bShift);
4441 srcbits = (char*)srcbits - bmpImage->bytes_per_line;
4442 dstbits += linebytes;
4444 } else {
4445 goto notsupported;
4447 break;
4449 default:
4450 notsupported:
4452 /* ==== any bmp format -> any 0888 dib ==== */
4453 int rShift,gShift,bShift;
4454 DWORD* dstpixel;
4456 WARN("from unknown %d bit bitmap (%lx,%lx,%lx) to 32 bit DIB (%lx,%lx,%lx)\n",
4457 bmpImage->depth, bmpImage->red_mask,
4458 bmpImage->green_mask, bmpImage->blue_mask,
4459 rDst,gDst,bDst);
4461 rShift=X11DRV_DIB_MaskToShift(rDst);
4462 gShift=X11DRV_DIB_MaskToShift(gDst);
4463 bShift=X11DRV_DIB_MaskToShift(bDst);
4464 for (h = lines - 1; h >= 0; h--) {
4465 dstpixel=(DWORD*)dstbits;
4466 for (x = 0; x < dstwidth; x++) {
4467 COLORREF srcval;
4468 srcval=X11DRV_PALETTE_ToLogical(XGetPixel(bmpImage, x, h));
4469 *dstpixel++=(GetRValue(srcval) << rShift) |
4470 (GetGValue(srcval) << gShift) |
4471 (GetBValue(srcval) << bShift);
4473 dstbits += linebytes;
4476 break;
4480 /***********************************************************************
4481 * X11DRV_DIB_SetImageBits
4483 * Transfer the bits to an X image.
4484 * Helper function for SetDIBits() and SetDIBitsToDevice().
4486 static int X11DRV_DIB_SetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4488 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4489 XImage *bmpImage;
4491 wine_tsx11_lock();
4492 if (descr->image)
4493 bmpImage = descr->image;
4494 else {
4495 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4496 descr->infoWidth, lines, 32, 0 );
4497 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4498 if(bmpImage->data == NULL) {
4499 ERR("Out of memory!\n");
4500 XDestroyImage( bmpImage );
4501 wine_tsx11_unlock();
4502 return lines;
4506 TRACE("Dib: depth=%d r=%lx g=%lx b=%lx\n",
4507 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4508 TRACE("Bmp: depth=%d/%d r=%lx g=%lx b=%lx\n",
4509 bmpImage->depth,bmpImage->bits_per_pixel,
4510 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4512 /* Transfer the pixels */
4513 switch(descr->infoBpp)
4515 case 1:
4516 X11DRV_DIB_SetImageBits_1( descr->lines, descr->bits, descr->infoWidth,
4517 descr->width, descr->xSrc, (int *)(descr->colorMap),
4518 bmpImage, descr->dibpitch );
4519 break;
4520 case 4:
4521 if (descr->compression) {
4522 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4523 descr->width, descr->height, AllPlanes, ZPixmap,
4524 bmpImage, descr->xSrc, descr->ySrc );
4526 X11DRV_DIB_SetImageBits_RLE4( descr->lines, descr->bits,
4527 descr->infoWidth, descr->width,
4528 descr->xSrc, (int *)(descr->colorMap),
4529 bmpImage );
4530 } else
4531 X11DRV_DIB_SetImageBits_4( descr->lines, descr->bits,
4532 descr->infoWidth, descr->width,
4533 descr->xSrc, (int*)(descr->colorMap),
4534 bmpImage, descr->dibpitch );
4535 break;
4536 case 8:
4537 if (descr->compression) {
4538 XGetSubImage( gdi_display, descr->drawable, descr->xDest, descr->yDest,
4539 descr->width, descr->height, AllPlanes, ZPixmap,
4540 bmpImage, descr->xSrc, descr->ySrc );
4541 X11DRV_DIB_SetImageBits_RLE8( descr->lines, descr->bits,
4542 descr->infoWidth, descr->width,
4543 descr->xSrc, (int *)(descr->colorMap),
4544 bmpImage );
4545 } else
4546 X11DRV_DIB_SetImageBits_8( descr->lines, descr->bits,
4547 descr->infoWidth, descr->width,
4548 descr->xSrc, (int *)(descr->colorMap),
4549 bmpImage, descr->dibpitch );
4550 break;
4551 case 15:
4552 case 16:
4553 X11DRV_DIB_SetImageBits_16( descr->lines, descr->bits,
4554 descr->infoWidth, descr->width,
4555 descr->xSrc, descr->physDev,
4556 descr->rMask, descr->gMask, descr->bMask,
4557 bmpImage, descr->dibpitch);
4558 break;
4559 case 24:
4560 X11DRV_DIB_SetImageBits_24( descr->lines, descr->bits,
4561 descr->infoWidth, descr->width,
4562 descr->xSrc, descr->physDev,
4563 descr->rMask, descr->gMask, descr->bMask,
4564 bmpImage, descr->dibpitch);
4565 break;
4566 case 32:
4567 X11DRV_DIB_SetImageBits_32( descr->lines, descr->bits,
4568 descr->infoWidth, descr->width,
4569 descr->xSrc, descr->physDev,
4570 descr->rMask, descr->gMask, descr->bMask,
4571 bmpImage, descr->dibpitch);
4572 break;
4573 default:
4574 WARN("(%d): Invalid depth\n", descr->infoBpp );
4575 break;
4578 TRACE("XPutImage(%ld,%p,%p,%d,%d,%d,%d,%d,%d)\n",
4579 descr->drawable, descr->gc, bmpImage,
4580 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4581 descr->width, descr->height);
4582 #ifdef HAVE_LIBXXSHM
4583 if (descr->useShm)
4585 XShmPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4586 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4587 descr->width, descr->height, FALSE );
4588 XSync( gdi_display, 0 );
4590 else
4591 #endif
4592 XPutImage( gdi_display, descr->drawable, descr->gc, bmpImage,
4593 descr->xSrc, descr->ySrc, descr->xDest, descr->yDest,
4594 descr->width, descr->height );
4596 if (!descr->image) XDestroyImage( bmpImage );
4597 wine_tsx11_unlock();
4598 return lines;
4601 /***********************************************************************
4602 * X11DRV_DIB_GetImageBits
4604 * Transfer the bits from an X image.
4606 static int X11DRV_DIB_GetImageBits( const X11DRV_DIB_IMAGEBITS_DESCR *descr )
4608 int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
4609 XImage *bmpImage;
4611 wine_tsx11_lock();
4612 if (descr->image)
4613 bmpImage = descr->image;
4614 else {
4615 bmpImage = XCreateImage( gdi_display, visual, descr->depth, ZPixmap, 0, NULL,
4616 descr->infoWidth, lines, 32, 0 );
4617 bmpImage->data = calloc( lines, bmpImage->bytes_per_line );
4618 if(bmpImage->data == NULL) {
4619 ERR("Out of memory!\n");
4620 XDestroyImage( bmpImage );
4621 wine_tsx11_unlock();
4622 return lines;
4626 if (descr->useShm)
4628 int saveRed, saveGreen, saveBlue;
4630 TRACE("XShmGetImage(%p, %ld, %p, %d, %d, %ld)\n",
4631 gdi_display, descr->drawable, bmpImage,
4632 descr->xSrc, descr->ySrc, AllPlanes);
4634 /* We must save and restore the bmpImage's masks in order
4635 * to preserve them across the call to XShmGetImage, which
4636 * decides to eleminate them since it doesn't happen to know
4637 * what the format of the image is supposed to be, even though
4638 * we do. */
4639 saveRed = bmpImage->red_mask;
4640 saveBlue= bmpImage->blue_mask;
4641 saveGreen = bmpImage->green_mask;
4643 XShmGetImage( gdi_display, descr->drawable, bmpImage,
4644 descr->xSrc, descr->ySrc, AllPlanes);
4646 bmpImage->red_mask = saveRed;
4647 bmpImage->blue_mask = saveBlue;
4648 bmpImage->green_mask = saveGreen;
4650 else
4652 TRACE("XGetSubImage(%p,%ld,%d,%d,%d,%d,%ld,%d,%p,%d,%d)\n",
4653 gdi_display, descr->drawable, descr->xSrc, descr->ySrc, descr->width,
4654 lines, AllPlanes, ZPixmap, bmpImage, descr->xDest, descr->yDest);
4655 XGetSubImage( gdi_display, descr->drawable, descr->xSrc, descr->ySrc,
4656 descr->width, lines, AllPlanes, ZPixmap,
4657 bmpImage, descr->xDest, descr->yDest );
4660 TRACE("Dib: depth=%2d r=%lx g=%lx b=%lx\n",
4661 descr->infoBpp,descr->rMask,descr->gMask,descr->bMask);
4662 TRACE("Bmp: depth=%2d/%2d r=%lx g=%lx b=%lx\n",
4663 bmpImage->depth,bmpImage->bits_per_pixel,
4664 bmpImage->red_mask,bmpImage->green_mask,bmpImage->blue_mask);
4665 /* Transfer the pixels */
4666 switch(descr->infoBpp)
4668 case 1:
4669 X11DRV_DIB_GetImageBits_1( descr->lines,(LPVOID)descr->bits,
4670 descr->infoWidth, descr->width,
4671 descr->colorMap, descr->palentry,
4672 bmpImage, descr->dibpitch );
4673 break;
4675 case 4:
4676 if (descr->compression)
4677 FIXME("Compression not yet supported!\n");
4678 else
4679 X11DRV_DIB_GetImageBits_4( descr->lines,(LPVOID)descr->bits,
4680 descr->infoWidth, descr->width,
4681 descr->colorMap, descr->palentry,
4682 bmpImage, descr->dibpitch );
4683 break;
4685 case 8:
4686 if (descr->compression)
4687 FIXME("Compression not yet supported!\n");
4688 else
4689 X11DRV_DIB_GetImageBits_8( descr->lines, (LPVOID)descr->bits,
4690 descr->infoWidth, descr->width,
4691 descr->colorMap, descr->palentry,
4692 bmpImage, descr->dibpitch );
4693 break;
4694 case 15:
4695 case 16:
4696 X11DRV_DIB_GetImageBits_16( descr->lines, (LPVOID)descr->bits,
4697 descr->infoWidth,descr->width,
4698 descr->palentry,
4699 descr->rMask, descr->gMask, descr->bMask,
4700 bmpImage, descr->dibpitch );
4701 break;
4703 case 24:
4704 X11DRV_DIB_GetImageBits_24( descr->lines, (LPVOID)descr->bits,
4705 descr->infoWidth,descr->width,
4706 descr->palentry,
4707 descr->rMask, descr->gMask, descr->bMask,
4708 bmpImage, descr->dibpitch);
4709 break;
4711 case 32:
4712 X11DRV_DIB_GetImageBits_32( descr->lines, (LPVOID)descr->bits,
4713 descr->infoWidth, descr->width,
4714 descr->palentry,
4715 descr->rMask, descr->gMask, descr->bMask,
4716 bmpImage, descr->dibpitch);
4717 break;
4719 default:
4720 WARN("(%d): Invalid depth\n", descr->infoBpp );
4721 break;
4724 if (!descr->image) XDestroyImage( bmpImage );
4725 wine_tsx11_unlock();
4726 return lines;
4729 /*************************************************************************
4730 * X11DRV_SetDIBitsToDevice
4733 INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWORD cx,
4734 DWORD cy, INT xSrc, INT ySrc,
4735 UINT startscan, UINT lines, LPCVOID bits,
4736 const BITMAPINFO *info, UINT coloruse )
4738 X11DRV_DIB_IMAGEBITS_DESCR descr;
4739 DWORD width;
4740 INT result;
4741 int height;
4742 BOOL top_down;
4743 POINT pt;
4744 DC *dc = physDev->dc;
4746 if (DIB_GetBitmapInfo( &info->bmiHeader, &width, &height,
4747 &descr.infoBpp, &descr.compression ) == -1)
4748 return 0;
4749 top_down = (height < 0);
4750 if (top_down) height = -height;
4752 pt.x = xDest;
4753 pt.y = yDest;
4754 LPtoDP(physDev->hdc, &pt, 1);
4756 if (!lines || (startscan >= height)) return 0;
4757 if (!top_down && startscan + lines > height) lines = height - startscan;
4759 /* make xSrc,ySrc point to the upper-left corner, not the lower-left one,
4760 * and clamp all values to fit inside [startscan,startscan+lines]
4762 if (ySrc + cy <= startscan + lines)
4764 INT y = startscan + lines - (ySrc + cy);
4765 if (ySrc < startscan) cy -= (startscan - ySrc);
4766 if (!top_down)
4768 /* avoid getting unnecessary lines */
4769 ySrc = 0;
4770 if (y >= lines) return 0;
4771 lines -= y;
4773 else
4775 if (y >= lines) return lines;
4776 ySrc = y; /* need to get all lines in top down mode */
4779 else
4781 if (ySrc >= startscan + lines) return lines;
4782 pt.y += ySrc + cy - (startscan + lines);
4783 cy = startscan + lines - ySrc;
4784 ySrc = 0;
4785 if (cy > lines) cy = lines;
4787 if (xSrc >= width) return lines;
4788 if (xSrc + cx >= width) cx = width - xSrc;
4789 if (!cx || !cy) return lines;
4791 X11DRV_SetupGCForText( physDev ); /* To have the correct colors */
4792 TSXSetFunction(gdi_display, physDev->gc, X11DRV_XROPfunction[dc->ROPmode-1]);
4794 switch (descr.infoBpp)
4796 case 1:
4797 case 4:
4798 case 8:
4799 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4800 coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
4801 dc->bitsPerPixel, info, &descr.nColorMap );
4802 if (!descr.colorMap) return 0;
4803 descr.rMask = descr.gMask = descr.bMask = 0;
4804 break;
4805 case 15:
4806 case 16:
4807 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4808 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4809 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4810 descr.colorMap = 0;
4811 break;
4813 case 24:
4814 case 32:
4815 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
4816 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4817 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4818 descr.colorMap = 0;
4819 break;
4822 descr.physDev = physDev;
4823 descr.bits = bits;
4824 descr.image = NULL;
4825 descr.palentry = NULL;
4826 descr.lines = top_down ? -lines : lines;
4827 descr.infoWidth = width;
4828 descr.depth = dc->bitsPerPixel;
4829 descr.drawable = physDev->drawable;
4830 descr.gc = physDev->gc;
4831 descr.xSrc = xSrc;
4832 descr.ySrc = ySrc;
4833 descr.xDest = physDev->org.x + pt.x;
4834 descr.yDest = physDev->org.y + pt.y;
4835 descr.width = cx;
4836 descr.height = cy;
4837 descr.useShm = FALSE;
4838 descr.dibpitch = ((width * descr.infoBpp + 31) &~31) / 8;
4840 result = X11DRV_DIB_SetImageBits( &descr );
4842 if (descr.infoBpp <= 8)
4843 HeapFree(GetProcessHeap(), 0, descr.colorMap);
4844 return result;
4847 /***********************************************************************
4848 * SetDIBits (X11DRV.@)
4850 INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
4851 UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
4853 X11DRV_DIB_IMAGEBITS_DESCR descr;
4854 BITMAPOBJ *bmp;
4855 int height, tmpheight;
4856 INT result;
4858 descr.physDev = physDev;
4860 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &height,
4861 &descr.infoBpp, &descr.compression ) == -1)
4862 return 0;
4864 tmpheight = height;
4865 if (height < 0) height = -height;
4866 if (!lines || (startscan >= height))
4867 return 0;
4869 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC ))) return 0;
4871 if (startscan + lines > height) lines = height - startscan;
4873 switch (descr.infoBpp)
4875 case 1:
4876 case 4:
4877 case 8:
4878 descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
4879 coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
4880 bmp->bitmap.bmBitsPixel,
4881 info, &descr.nColorMap );
4882 if (!descr.colorMap)
4884 GDI_ReleaseObj( hbitmap );
4885 return 0;
4887 descr.rMask = descr.gMask = descr.bMask = 0;
4888 break;
4889 case 15:
4890 case 16:
4891 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4892 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4893 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4894 descr.colorMap = 0;
4895 break;
4897 case 24:
4898 case 32:
4899 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
4900 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
4901 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
4902 descr.colorMap = 0;
4903 break;
4905 default: break;
4908 descr.bits = bits;
4909 descr.image = NULL;
4910 descr.palentry = NULL;
4911 descr.lines = tmpheight >= 0 ? lines : -lines;
4912 descr.depth = bmp->bitmap.bmBitsPixel;
4913 descr.drawable = (Pixmap)bmp->physBitmap;
4914 descr.gc = BITMAP_GC(bmp);
4915 descr.xSrc = 0;
4916 descr.ySrc = 0;
4917 descr.xDest = 0;
4918 descr.yDest = height - startscan - lines;
4919 descr.width = bmp->bitmap.bmWidth;
4920 descr.height = lines;
4921 descr.useShm = FALSE;
4922 descr.dibpitch = ((descr.infoWidth * descr.infoBpp + 31) &~31) / 8;
4923 X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
4924 result = X11DRV_DIB_SetImageBits( &descr );
4925 X11DRV_DIB_Unlock(bmp, TRUE);
4927 if (descr.colorMap) HeapFree(GetProcessHeap(), 0, descr.colorMap);
4929 GDI_ReleaseObj( hbitmap );
4930 return result;
4933 /***********************************************************************
4934 * GetDIBits (X11DRV.@)
4936 INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan, UINT lines,
4937 LPVOID bits, BITMAPINFO *info, UINT coloruse )
4939 X11DRV_DIBSECTION *dib;
4940 X11DRV_DIB_IMAGEBITS_DESCR descr;
4941 PALETTEOBJ * palette;
4942 BITMAPOBJ *bmp;
4943 int height;
4944 DC *dc = physDev->dc;
4946 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
4947 return 0;
4948 if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
4950 GDI_ReleaseObj( dc->hPalette );
4951 return 0;
4953 dib = (X11DRV_DIBSECTION *) bmp->dib;
4955 TRACE("%u scanlines of (%i,%i) -> (%i,%i) starting from %u\n",
4956 lines, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
4957 (int)info->bmiHeader.biWidth, (int)info->bmiHeader.biHeight,
4958 startscan );
4960 if( lines > bmp->bitmap.bmHeight ) lines = bmp->bitmap.bmHeight;
4962 height = info->bmiHeader.biHeight;
4963 if (height < 0) height = -height;
4964 if( lines > height ) lines = height;
4965 /* Top-down images have a negative biHeight, the scanlines of theses images
4966 * were inverted in X11DRV_DIB_GetImageBits_xx
4967 * To prevent this we simply change the sign of lines
4968 * (the number of scan lines to copy).
4969 * Negative lines are correctly handled by X11DRV_DIB_GetImageBits_xx.
4971 if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
4973 if( startscan >= bmp->bitmap.bmHeight )
4975 lines = 0;
4976 goto done;
4979 if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
4980 &descr.infoBpp, &descr.compression ) == -1)
4982 lines = 0;
4983 goto done;
4986 switch (descr.infoBpp)
4988 case 1:
4989 case 4:
4990 case 8:
4991 descr.rMask= descr.gMask = descr.bMask = 0;
4992 break;
4993 case 15:
4994 case 16:
4995 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0x7c00;
4996 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x03e0;
4997 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x001f;
4998 break;
4999 case 24:
5000 case 32:
5001 descr.rMask = (descr.compression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : 0xff0000;
5002 descr.gMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : 0x00ff00;
5003 descr.bMask = (descr.compression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : 0x0000ff;
5004 break;
5007 descr.physDev = physDev;
5008 descr.palentry = palette->logpalette.palPalEntry;
5009 descr.bits = bits;
5010 descr.image = NULL;
5011 descr.lines = lines;
5012 descr.depth = bmp->bitmap.bmBitsPixel;
5013 descr.drawable = (Pixmap)bmp->physBitmap;
5014 descr.gc = BITMAP_GC(bmp);
5015 descr.width = bmp->bitmap.bmWidth;
5016 descr.height = bmp->bitmap.bmHeight;
5017 descr.colorMap = info->bmiColors;
5018 descr.xDest = 0;
5019 descr.yDest = 0;
5020 descr.xSrc = 0;
5022 if (descr.lines > 0)
5024 descr.ySrc = (descr.height-1) - (startscan + (lines-1));
5026 else
5028 descr.ySrc = startscan;
5030 #ifdef HAVE_LIBXXSHM
5031 descr.useShm = dib ? (dib->shminfo.shmid != -1) : FALSE;
5032 #else
5033 descr.useShm = FALSE;
5034 #endif
5035 descr.dibpitch = dib ? (dib->dibSection.dsBm.bmWidthBytes)
5036 : (((descr.infoWidth * descr.infoBpp + 31) &~31) / 8);
5038 X11DRV_DIB_Lock(bmp, DIB_Status_GdiMod, FALSE);
5039 X11DRV_DIB_GetImageBits( &descr );
5040 X11DRV_DIB_Unlock(bmp, TRUE);
5042 if(info->bmiHeader.biSizeImage == 0) /* Fill in biSizeImage */
5043 info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(
5044 info->bmiHeader.biWidth,
5045 info->bmiHeader.biHeight,
5046 info->bmiHeader.biBitCount );
5048 if (descr.compression == BI_BITFIELDS)
5050 *(DWORD *)info->bmiColors = descr.rMask;
5051 *((DWORD *)info->bmiColors+1) = descr.gMask;
5052 *((DWORD *)info->bmiColors+2) = descr.bMask;
5054 else
5056 /* if RLE or JPEG compression were supported,
5057 * this line would be invalid. */
5058 info->bmiHeader.biCompression = 0;
5061 done:
5062 GDI_ReleaseObj( dc->hPalette );
5063 GDI_ReleaseObj( hbitmap );
5064 return lines;
5067 /***********************************************************************
5068 * DIB_DoProtectDIBSection
5070 static void X11DRV_DIB_DoProtectDIBSection( BITMAPOBJ *bmp, DWORD new_prot )
5072 DIBSECTION *dib = bmp->dib;
5073 INT effHeight = dib->dsBm.bmHeight >= 0? dib->dsBm.bmHeight
5074 : -dib->dsBm.bmHeight;
5075 /* use the biSizeImage data as the memory size only if we're dealing with a
5076 compressed image where the value is set. Otherwise, calculate based on
5077 width * height */
5078 INT totalSize = dib->dsBmih.biSizeImage && dib->dsBmih.biCompression != BI_RGB
5079 ? dib->dsBmih.biSizeImage
5080 : dib->dsBm.bmWidthBytes * effHeight;
5081 DWORD old_prot;
5083 VirtualProtect(dib->dsBm.bmBits, totalSize, new_prot, &old_prot);
5084 TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
5087 /***********************************************************************
5088 * X11DRV_DIB_DoUpdateDIBSection
5090 static void X11DRV_DIB_DoCopyDIBSection(BITMAPOBJ *bmp, BOOL toDIB,
5091 void *colorMap, int nColorMap,
5092 Drawable dest,
5093 DWORD xSrc, DWORD ySrc,
5094 DWORD xDest, DWORD yDest,
5095 DWORD width, DWORD height)
5097 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5098 X11DRV_DIB_IMAGEBITS_DESCR descr;
5100 if (DIB_GetBitmapInfo( &dib->dibSection.dsBmih, &descr.infoWidth, &descr.lines,
5101 &descr.infoBpp, &descr.compression ) == -1)
5102 return;
5104 descr.physDev = NULL;
5105 descr.palentry = NULL;
5106 descr.image = dib->image;
5107 descr.colorMap = colorMap;
5108 descr.nColorMap = nColorMap;
5109 descr.bits = dib->dibSection.dsBm.bmBits;
5110 descr.depth = bmp->bitmap.bmBitsPixel;
5112 switch (descr.infoBpp)
5114 case 1:
5115 case 4:
5116 case 8:
5117 descr.rMask = descr.gMask = descr.bMask = 0;
5118 break;
5119 case 15:
5120 case 16:
5121 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0x7c00;
5122 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x03e0;
5123 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x001f;
5124 break;
5126 case 24:
5127 case 32:
5128 descr.rMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[0] : 0xff0000;
5129 descr.gMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[1] : 0x00ff00;
5130 descr.bMask = (descr.compression == BI_BITFIELDS) ? dib->dibSection.dsBitfields[2] : 0x0000ff;
5131 break;
5134 /* Hack for now */
5135 descr.drawable = dest;
5136 descr.gc = BITMAP_GC(bmp);
5137 descr.xSrc = xSrc;
5138 descr.ySrc = ySrc;
5139 descr.xDest = xDest;
5140 descr.yDest = yDest;
5141 descr.width = width;
5142 descr.height = height;
5143 #ifdef HAVE_LIBXXSHM
5144 descr.useShm = (dib->shminfo.shmid != -1);
5145 #else
5146 descr.useShm = FALSE;
5147 #endif
5148 descr.dibpitch = dib->dibSection.dsBm.bmWidthBytes;
5150 if (toDIB)
5152 TRACE("Copying from Pixmap to DIB bits\n");
5153 X11DRV_DIB_GetImageBits( &descr );
5155 else
5157 TRACE("Copying from DIB bits to Pixmap\n");
5158 X11DRV_DIB_SetImageBits( &descr );
5162 /***********************************************************************
5163 * X11DRV_DIB_CopyDIBSection
5165 void X11DRV_DIB_CopyDIBSection(X11DRV_PDEVICE *physDevSrc, X11DRV_PDEVICE *physDevDst,
5166 DWORD xSrc, DWORD ySrc, DWORD xDest, DWORD yDest,
5167 DWORD width, DWORD height)
5169 BITMAPOBJ *bmp;
5170 DC *dcSrc = physDevSrc->dc;
5171 DC *dcDst = physDevDst->dc;
5172 int nColorMap = 0, *colorMap = NULL, aColorMap = FALSE;
5174 TRACE("(%p,%p,%ld,%ld,%ld,%ld,%ld,%ld)\n", dcSrc, dcDst,
5175 xSrc, ySrc, xDest, yDest, width, height);
5176 /* this function is meant as an optimization for BitBlt,
5177 * not to be called otherwise */
5178 if (!(dcSrc->flags & DC_MEMORY)) {
5179 ERR("called for non-memory source DC!?\n");
5180 return;
5183 bmp = (BITMAPOBJ *)GDI_GetObjPtr( dcSrc->hBitmap, BITMAP_MAGIC );
5184 if (!(bmp && bmp->dib)) {
5185 ERR("called for non-DIBSection!?\n");
5186 GDI_ReleaseObj( dcSrc->hBitmap );
5187 return;
5189 /* while BitBlt should already have made sure we only get
5190 * positive values, we should check for oversize values */
5191 if ((xSrc < bmp->bitmap.bmWidth) &&
5192 (ySrc < bmp->bitmap.bmHeight)) {
5193 if (xSrc + width > bmp->bitmap.bmWidth)
5194 width = bmp->bitmap.bmWidth - xSrc;
5195 if (ySrc + height > bmp->bitmap.bmHeight)
5196 height = bmp->bitmap.bmHeight - ySrc;
5197 /* if the source bitmap is 8bpp or less, we're supposed to use the
5198 * DC's palette for color conversion (not the DIB color table) */
5199 if (bmp->dib->dsBm.bmBitsPixel <= 8) {
5200 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5201 if ((!dcSrc->hPalette) ||
5202 (dcSrc->hPalette == GetStockObject(DEFAULT_PALETTE))) {
5203 /* HACK: no palette has been set in the source DC,
5204 * use the DIB colormap instead - this is necessary in some
5205 * cases since we need to do depth conversion in some places
5206 * where real Windows can just copy data straight over */
5207 colorMap = dib->colorMap;
5208 nColorMap = dib->nColorMap;
5209 } else {
5210 colorMap = X11DRV_DIB_BuildColorMap( physDevSrc, (WORD)-1,
5211 bmp->dib->dsBm.bmBitsPixel,
5212 (BITMAPINFO*)&(bmp->dib->dsBmih),
5213 &nColorMap );
5214 if (colorMap) aColorMap = TRUE;
5217 /* perform the copy */
5218 X11DRV_DIB_DoCopyDIBSection(bmp, FALSE, colorMap, nColorMap,
5219 physDevDst->drawable, xSrc, ySrc,
5220 physDevDst->org.x + xDest, physDevDst->org.y + yDest,
5221 width, height);
5222 /* free color mapping */
5223 if (aColorMap)
5224 HeapFree(GetProcessHeap(), 0, colorMap);
5226 GDI_ReleaseObj( dcSrc->hBitmap );
5229 /***********************************************************************
5230 * X11DRV_DIB_DoUpdateDIBSection
5232 static void X11DRV_DIB_DoUpdateDIBSection(BITMAPOBJ *bmp, BOOL toDIB)
5234 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5235 X11DRV_DIB_DoCopyDIBSection(bmp, toDIB, dib->colorMap, dib->nColorMap,
5236 (Drawable)bmp->physBitmap, 0, 0, 0, 0,
5237 bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
5240 /***********************************************************************
5241 * X11DRV_DIB_FaultHandler
5243 static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
5245 BITMAPOBJ *bmp;
5246 INT state;
5248 bmp = (BITMAPOBJ *)GDI_GetObjPtr( (HBITMAP)res, BITMAP_MAGIC );
5249 if (!bmp) return FALSE;
5251 state = X11DRV_DIB_Lock(bmp, DIB_Status_None, FALSE);
5252 if (state != DIB_Status_InSync) {
5253 /* no way to tell whether app needs read or write yet,
5254 * try read first */
5255 X11DRV_DIB_Coerce(bmp, DIB_Status_InSync, FALSE);
5256 } else {
5257 /* hm, apparently the app must have write access */
5258 X11DRV_DIB_Coerce(bmp, DIB_Status_AppMod, FALSE);
5260 X11DRV_DIB_Unlock(bmp, TRUE);
5262 GDI_ReleaseObj( (HBITMAP)res );
5263 return TRUE;
5266 /***********************************************************************
5267 * X11DRV_DIB_Coerce
5269 INT X11DRV_DIB_Coerce(BITMAPOBJ *bmp, INT req, BOOL lossy)
5271 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5272 INT ret = DIB_Status_None;
5274 if (dib) {
5275 EnterCriticalSection(&(dib->lock));
5276 ret = dib->status;
5277 switch (req) {
5278 case DIB_Status_GdiMod:
5279 /* GDI access - request to draw on pixmap */
5280 switch (dib->status)
5282 default:
5283 case DIB_Status_None:
5284 dib->p_status = DIB_Status_GdiMod;
5285 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5286 break;
5288 case DIB_Status_GdiMod:
5289 TRACE("GdiMod requested in status GdiMod\n" );
5290 break;
5292 case DIB_Status_InSync:
5293 TRACE("GdiMod requested in status InSync\n" );
5294 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5295 dib->status = DIB_Status_GdiMod;
5296 dib->p_status = DIB_Status_InSync;
5297 break;
5299 case DIB_Status_AuxMod:
5300 TRACE("GdiMod requested in status AuxMod\n" );
5301 if (lossy) dib->status = DIB_Status_GdiMod;
5302 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_GdiMod);
5303 dib->p_status = DIB_Status_AuxMod;
5304 if (dib->status != DIB_Status_AppMod) {
5305 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5306 break;
5308 /* fall through if copy_aux() had to change to AppMod state */
5310 case DIB_Status_AppMod:
5311 TRACE("GdiMod requested in status AppMod\n" );
5312 if (!lossy) {
5313 /* make it readonly to avoid app changing data while we copy */
5314 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5315 X11DRV_DIB_DoUpdateDIBSection( bmp, FALSE );
5317 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5318 dib->p_status = DIB_Status_AppMod;
5319 dib->status = DIB_Status_GdiMod;
5320 break;
5322 break;
5324 case DIB_Status_InSync:
5325 /* App access - request access to read DIB surface */
5326 /* (typically called from signal handler) */
5327 switch (dib->status)
5329 default:
5330 case DIB_Status_None:
5331 /* shouldn't happen from signal handler */
5332 break;
5334 case DIB_Status_AuxMod:
5335 TRACE("InSync requested in status AuxMod\n" );
5336 if (lossy) dib->status = DIB_Status_InSync;
5337 else {
5338 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5339 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_InSync);
5341 if (dib->status != DIB_Status_GdiMod) {
5342 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5343 break;
5345 /* fall through if copy_aux() had to change to GdiMod state */
5347 case DIB_Status_GdiMod:
5348 TRACE("InSync requested in status GdiMod\n" );
5349 if (!lossy) {
5350 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5351 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5353 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5354 dib->status = DIB_Status_InSync;
5355 break;
5357 case DIB_Status_InSync:
5358 TRACE("InSync requested in status InSync\n" );
5359 /* shouldn't happen from signal handler */
5360 break;
5362 case DIB_Status_AppMod:
5363 TRACE("InSync requested in status AppMod\n" );
5364 /* no reason to do anything here, and this
5365 * shouldn't happen from signal handler */
5366 break;
5368 break;
5370 case DIB_Status_AppMod:
5371 /* App access - request access to write DIB surface */
5372 /* (typically called from signal handler) */
5373 switch (dib->status)
5375 default:
5376 case DIB_Status_None:
5377 /* shouldn't happen from signal handler */
5378 break;
5380 case DIB_Status_AuxMod:
5381 TRACE("AppMod requested in status AuxMod\n" );
5382 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5383 if (lossy) dib->status = DIB_Status_AppMod;
5384 else (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5385 if (dib->status != DIB_Status_GdiMod)
5386 break;
5387 /* fall through if copy_aux() had to change to GdiMod state */
5389 case DIB_Status_GdiMod:
5390 TRACE("AppMod requested in status GdiMod\n" );
5391 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5392 if (!lossy) X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5393 dib->status = DIB_Status_AppMod;
5394 break;
5396 case DIB_Status_InSync:
5397 TRACE("AppMod requested in status InSync\n" );
5398 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5399 dib->status = DIB_Status_AppMod;
5400 break;
5402 case DIB_Status_AppMod:
5403 TRACE("AppMod requested in status AppMod\n" );
5404 /* shouldn't happen from signal handler */
5405 break;
5407 break;
5409 case DIB_Status_AuxMod:
5410 if (dib->status == DIB_Status_None) {
5411 dib->p_status = req;
5412 } else {
5413 if (dib->status != DIB_Status_AuxMod)
5414 dib->p_status = dib->status;
5415 dib->status = DIB_Status_AuxMod;
5417 break;
5418 /* it is up to the caller to do the copy/conversion, probably
5419 * using the return value to decide where to copy from */
5421 LeaveCriticalSection(&(dib->lock));
5423 return ret;
5426 /***********************************************************************
5427 * X11DRV_DIB_Lock
5429 INT X11DRV_DIB_Lock(BITMAPOBJ *bmp, INT req, BOOL lossy)
5431 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5432 INT ret = DIB_Status_None;
5434 if (dib) {
5435 TRACE("Locking %p from thread %08lx\n", bmp, GetCurrentThreadId());
5436 EnterCriticalSection(&(dib->lock));
5437 ret = dib->status;
5438 if (req != DIB_Status_None)
5439 X11DRV_DIB_Coerce(bmp, req, lossy);
5441 return ret;
5444 /***********************************************************************
5445 * X11DRV_DIB_Unlock
5447 void X11DRV_DIB_Unlock(BITMAPOBJ *bmp, BOOL commit)
5449 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5451 if (dib) {
5452 switch (dib->status)
5454 default:
5455 case DIB_Status_None:
5456 /* in case anyone is wondering, this is the "signal handler doesn't
5457 * work" case, where we always have to be ready for app access */
5458 if (commit) {
5459 switch (dib->p_status)
5461 case DIB_Status_AuxMod:
5462 TRACE("Unlocking and syncing from AuxMod\n" );
5463 (*dib->copy_aux)(dib->aux_ctx, DIB_Status_AppMod);
5464 if (dib->status != DIB_Status_None) {
5465 dib->p_status = dib->status;
5466 dib->status = DIB_Status_None;
5468 if (dib->p_status != DIB_Status_GdiMod)
5469 break;
5470 /* fall through if copy_aux() had to change to GdiMod state */
5472 case DIB_Status_GdiMod:
5473 TRACE("Unlocking and syncing from GdiMod\n" );
5474 X11DRV_DIB_DoUpdateDIBSection( bmp, TRUE );
5475 break;
5477 default:
5478 TRACE("Unlocking without needing to sync\n" );
5479 break;
5482 else TRACE("Unlocking with no changes\n");
5483 dib->p_status = DIB_Status_None;
5484 break;
5486 case DIB_Status_GdiMod:
5487 TRACE("Unlocking in status GdiMod\n" );
5488 /* DIB was protected in Coerce */
5489 if (!commit) {
5490 /* no commit, revert to InSync if applicable */
5491 if ((dib->p_status == DIB_Status_InSync) ||
5492 (dib->p_status == DIB_Status_AppMod)) {
5493 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READONLY );
5494 dib->status = DIB_Status_InSync;
5497 break;
5499 case DIB_Status_InSync:
5500 TRACE("Unlocking in status InSync\n" );
5501 /* DIB was already protected in Coerce */
5502 break;
5504 case DIB_Status_AppMod:
5505 TRACE("Unlocking in status AppMod\n" );
5506 /* DIB was already protected in Coerce */
5507 /* this case is ordinary only called from the signal handler,
5508 * so we don't bother to check for !commit */
5509 break;
5511 case DIB_Status_AuxMod:
5512 TRACE("Unlocking in status AuxMod\n" );
5513 if (commit) {
5514 /* DIB may need protection now */
5515 if ((dib->p_status == DIB_Status_InSync) ||
5516 (dib->p_status == DIB_Status_AppMod))
5517 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_NOACCESS );
5518 } else {
5519 /* no commit, revert to previous state */
5520 if (dib->p_status != DIB_Status_None)
5521 dib->status = dib->p_status;
5522 /* no protections changed */
5524 dib->p_status = DIB_Status_None;
5525 break;
5527 LeaveCriticalSection(&(dib->lock));
5528 TRACE("Unlocked %p\n", bmp);
5532 /***********************************************************************
5533 * X11DRV_CoerceDIBSection2
5535 INT X11DRV_CoerceDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5537 BITMAPOBJ *bmp;
5538 INT ret;
5540 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5541 if (!bmp) return DIB_Status_None;
5542 ret = X11DRV_DIB_Coerce(bmp, req, lossy);
5543 GDI_ReleaseObj( hBmp );
5544 return ret;
5547 /***********************************************************************
5548 * X11DRV_LockDIBSection2
5550 INT X11DRV_LockDIBSection2(HBITMAP hBmp, INT req, BOOL lossy)
5552 BITMAPOBJ *bmp;
5553 INT ret;
5555 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5556 if (!bmp) return DIB_Status_None;
5557 ret = X11DRV_DIB_Lock(bmp, req, lossy);
5558 GDI_ReleaseObj( hBmp );
5559 return ret;
5562 /***********************************************************************
5563 * X11DRV_UnlockDIBSection2
5565 void X11DRV_UnlockDIBSection2(HBITMAP hBmp, BOOL commit)
5567 BITMAPOBJ *bmp;
5569 bmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5570 if (!bmp) return;
5571 X11DRV_DIB_Unlock(bmp, commit);
5572 GDI_ReleaseObj( hBmp );
5575 /***********************************************************************
5576 * X11DRV_CoerceDIBSection
5578 INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
5580 if (!physDev) return DIB_Status_None;
5581 return X11DRV_CoerceDIBSection2( physDev->dc->hBitmap, req, lossy );
5584 /***********************************************************************
5585 * X11DRV_LockDIBSection
5587 INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev, INT req, BOOL lossy)
5589 if (!physDev) return DIB_Status_None;
5590 if (!(physDev->dc->flags & DC_MEMORY)) return DIB_Status_None;
5592 return X11DRV_LockDIBSection2( physDev->dc->hBitmap, req, lossy );
5595 /***********************************************************************
5596 * X11DRV_UnlockDIBSection
5598 void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev, BOOL commit)
5600 if (!physDev) return;
5601 if (!(physDev->dc->flags & DC_MEMORY)) return;
5603 X11DRV_UnlockDIBSection2( physDev->dc->hBitmap, commit );
5607 #ifdef HAVE_LIBXXSHM
5608 /***********************************************************************
5609 * X11DRV_XShmErrorHandler
5612 static int XShmErrorHandler( Display *dpy, XErrorEvent *event, void *arg )
5614 return 1; /* FIXME: should check event contents */
5617 /***********************************************************************
5618 * X11DRV_XShmCreateImage
5621 static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
5622 XShmSegmentInfo* shminfo)
5624 XImage *image;
5626 wine_tsx11_lock();
5627 image = XShmCreateImage(gdi_display, visual, bpp, ZPixmap, NULL, shminfo, width, height);
5628 if (image)
5630 shminfo->shmid = shmget(IPC_PRIVATE, image->bytes_per_line * height,
5631 IPC_CREAT|0700);
5632 if( shminfo->shmid != -1 )
5634 shminfo->shmaddr = image->data = shmat(shminfo->shmid, 0, 0);
5635 if( shminfo->shmaddr != (char*)-1 )
5637 BOOL ok;
5639 shminfo->readOnly = FALSE;
5640 X11DRV_expect_error( gdi_display, XShmErrorHandler, NULL );
5641 ok = (XShmAttach( gdi_display, shminfo ) != 0);
5642 if (X11DRV_check_error()) ok = FALSE;
5643 if (ok)
5645 shmctl(shminfo->shmid, IPC_RMID, 0);
5646 wine_tsx11_unlock();
5647 return image; /* Success! */
5649 /* An error occured */
5650 shmdt(shminfo->shmaddr);
5652 shmctl(shminfo->shmid, IPC_RMID, 0);
5654 XFlush(gdi_display);
5655 XDestroyImage(image);
5656 image = NULL;
5658 wine_tsx11_unlock();
5659 return image;
5661 #endif /* HAVE_LIBXXSHM */
5664 /***********************************************************************
5665 * X11DRV_DIB_CreateDIBSection
5667 HBITMAP X11DRV_DIB_CreateDIBSection(
5668 X11DRV_PDEVICE *physDev, BITMAPINFO *bmi, UINT usage,
5669 LPVOID *bits, HANDLE section,
5670 DWORD offset, DWORD ovr_pitch)
5672 HBITMAP res = 0;
5673 BITMAPOBJ *bmp = NULL;
5674 X11DRV_DIBSECTION *dib = NULL;
5675 int *colorMap = NULL;
5676 int nColorMap;
5678 /* Fill BITMAP32 structure with DIB data */
5679 BITMAPINFOHEADER *bi = &bmi->bmiHeader;
5680 INT effHeight, totalSize;
5681 BITMAP bm;
5682 LPVOID mapBits = NULL;
5684 TRACE("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
5685 bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
5686 bi->biSizeImage, bi->biClrUsed, usage == DIB_PAL_COLORS? "PAL" : "RGB");
5688 effHeight = bi->biHeight >= 0 ? bi->biHeight : -bi->biHeight;
5689 bm.bmType = 0;
5690 bm.bmWidth = bi->biWidth;
5691 bm.bmHeight = effHeight;
5692 bm.bmWidthBytes = ovr_pitch ? ovr_pitch
5693 : DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
5694 bm.bmPlanes = bi->biPlanes;
5695 bm.bmBitsPixel = bi->biBitCount;
5696 bm.bmBits = NULL;
5698 /* Get storage location for DIB bits. Only use biSizeImage if it's valid and
5699 we're dealing with a compressed bitmap. Otherwise, use width * height. */
5700 totalSize = bi->biSizeImage && bi->biCompression != BI_RGB
5701 ? bi->biSizeImage : bm.bmWidthBytes * effHeight;
5703 if (section)
5705 SYSTEM_INFO SystemInfo;
5706 DWORD mapOffset;
5707 INT mapSize;
5709 GetSystemInfo( &SystemInfo );
5710 mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
5711 mapSize = totalSize + (offset - mapOffset);
5712 mapBits = MapViewOfFile( section,
5713 FILE_MAP_ALL_ACCESS,
5715 mapOffset,
5716 mapSize );
5717 bm.bmBits = (char *)mapBits + (offset - mapOffset);
5719 else if (ovr_pitch && offset)
5720 bm.bmBits = (LPVOID) offset;
5721 else {
5722 offset = 0;
5723 bm.bmBits = VirtualAlloc(NULL, totalSize,
5724 MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
5727 /* Create Color Map */
5728 if (bm.bmBits && bm.bmBitsPixel <= 8)
5729 colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS? physDev : NULL,
5730 usage, bm.bmBitsPixel, bmi, &nColorMap );
5732 /* Allocate Memory for DIB and fill structure */
5733 if (bm.bmBits)
5734 dib = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(X11DRV_DIBSECTION));
5735 if (dib)
5737 dib->dibSection.dsBm = bm;
5738 dib->dibSection.dsBmih = *bi;
5739 dib->dibSection.dsBmih.biSizeImage = totalSize;
5741 /* Set dsBitfields values */
5742 if ( usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
5744 dib->dibSection.dsBitfields[0] = dib->dibSection.dsBitfields[1] = dib->dibSection.dsBitfields[2] = 0;
5746 else switch( bi->biBitCount )
5748 case 15:
5749 case 16:
5750 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0x7c00;
5751 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x03e0;
5752 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x001f;
5753 break;
5755 case 24:
5756 case 32:
5757 dib->dibSection.dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)bmi->bmiColors : 0xff0000;
5758 dib->dibSection.dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 1) : 0x00ff00;
5759 dib->dibSection.dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)bmi->bmiColors + 2) : 0x0000ff;
5760 break;
5762 dib->dibSection.dshSection = section;
5763 dib->dibSection.dsOffset = offset;
5765 dib->status = DIB_Status_None;
5766 dib->nColorMap = nColorMap;
5767 dib->colorMap = colorMap;
5770 /* Create Device Dependent Bitmap and add DIB pointer */
5771 if (dib)
5773 res = CreateDIBitmap(physDev->hdc, bi, 0, NULL, bmi, usage);
5774 if (res)
5776 bmp = (BITMAPOBJ *) GDI_GetObjPtr(res, BITMAP_MAGIC);
5777 if (bmp) bmp->dib = (DIBSECTION *) dib;
5781 /* Create XImage */
5782 if (dib && bmp)
5784 #ifdef HAVE_LIBXXSHM
5785 if (TSXShmQueryExtension(gdi_display) &&
5786 (dib->image = X11DRV_XShmCreateImage( bm.bmWidth, effHeight,
5787 bmp->bitmap.bmBitsPixel, &dib->shminfo )) )
5789 ; /* Created Image */
5790 } else {
5791 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5792 dib->shminfo.shmid = -1;
5794 #else
5795 dib->image = X11DRV_DIB_CreateXImage( bm.bmWidth, effHeight, bmp->bitmap.bmBitsPixel );
5796 #endif
5799 /* Clean up in case of errors */
5800 if (!res || !bmp || !dib || !bm.bmBits || (bm.bmBitsPixel <= 8 && !colorMap))
5802 TRACE("got an error res=%08x, bmp=%p, dib=%p, bm.bmBits=%p\n",
5803 res, bmp, dib, bm.bmBits);
5804 if (bm.bmBits)
5806 if (section)
5807 UnmapViewOfFile(mapBits), bm.bmBits = NULL;
5808 else if (!offset)
5809 VirtualFree(bm.bmBits, 0L, MEM_RELEASE), bm.bmBits = NULL;
5812 if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
5813 if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
5814 if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
5815 if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
5816 if (res) { DeleteObject(res); res = 0; }
5818 else if (bm.bmBits)
5820 /* Install fault handler, if possible */
5821 InitializeCriticalSection(&(dib->lock));
5822 if (VIRTUAL_SetFaultHandler(bm.bmBits, X11DRV_DIB_FaultHandler, (LPVOID)res))
5824 X11DRV_DIB_DoProtectDIBSection( bmp, PAGE_READWRITE );
5825 if (dib) dib->status = DIB_Status_AppMod;
5829 /* Return BITMAP handle and storage location */
5830 if (bmp) GDI_ReleaseObj(res);
5831 if (bm.bmBits && bits) *bits = bm.bmBits;
5832 return res;
5835 /***********************************************************************
5836 * X11DRV_DIB_DeleteDIBSection
5838 void X11DRV_DIB_DeleteDIBSection(BITMAPOBJ *bmp)
5840 X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *) bmp->dib;
5842 if (dib->image)
5844 #ifdef HAVE_LIBXXSHM
5845 if (dib->shminfo.shmid != -1)
5847 TSXShmDetach (gdi_display, &(dib->shminfo));
5848 XDestroyImage (dib->image);
5849 shmdt (dib->shminfo.shmaddr);
5850 dib->shminfo.shmid = -1;
5852 else
5853 #endif
5854 XDestroyImage( dib->image );
5857 if (dib->colorMap)
5858 HeapFree(GetProcessHeap(), 0, dib->colorMap);
5860 DeleteCriticalSection(&(dib->lock));
5863 /***********************************************************************
5864 * SetDIBColorTable (X11DRV.@)
5866 UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, const RGBQUAD *colors )
5868 BITMAPOBJ * bmp;
5869 X11DRV_DIBSECTION *dib;
5870 UINT ret = 0;
5872 if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
5873 dib = (X11DRV_DIBSECTION *) bmp->dib;
5875 if (dib && dib->colorMap) {
5876 UINT end = count + start;
5877 if (end > dib->nColorMap) end = dib->nColorMap;
5879 * Changing color table might change the mapping between
5880 * DIB colors and X11 colors and thus alter the visible state
5881 * of the bitmap object.
5883 X11DRV_DIB_Lock(bmp, DIB_Status_AppMod, FALSE);
5884 X11DRV_DIB_GenColorMap( physDev, dib->colorMap, DIB_RGB_COLORS,
5885 dib->dibSection.dsBm.bmBitsPixel,
5886 TRUE, colors, start, end );
5887 X11DRV_DIB_Unlock(bmp, TRUE);
5888 ret = end - start;
5890 GDI_ReleaseObj( physDev->dc->hBitmap );
5891 return ret;
5894 /***********************************************************************
5895 * GetDIBColorTable (X11DRV.@)
5897 UINT X11DRV_GetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, RGBQUAD *colors )
5899 BITMAPOBJ * bmp;
5900 X11DRV_DIBSECTION *dib;
5901 UINT ret = 0;
5903 if (!(bmp = (BITMAPOBJ*)GDI_GetObjPtr( physDev->dc->hBitmap, BITMAP_MAGIC ))) return 0;
5904 dib = (X11DRV_DIBSECTION *) bmp->dib;
5906 if (dib && dib->colorMap) {
5907 UINT i, end = count + start;
5908 if (end > dib->nColorMap) end = dib->nColorMap;
5909 for (i = start; i < end; i++,colors++) {
5910 COLORREF col = X11DRV_PALETTE_ToLogical( dib->colorMap[i] );
5911 colors->rgbBlue = GetBValue(col);
5912 colors->rgbGreen = GetGValue(col);
5913 colors->rgbRed = GetRValue(col);
5914 colors->rgbReserved = 0;
5916 ret = end-start;
5918 GDI_ReleaseObj( physDev->dc->hBitmap );
5919 return ret;
5923 /**************************************************************************
5924 * X11DRV_DIB_CreateDIBFromPixmap
5926 * Allocates a packed DIB and copies the Pixmap data into it.
5927 * If bDeletePixmap is TRUE, the Pixmap passed in is deleted after the conversion.
5929 HGLOBAL X11DRV_DIB_CreateDIBFromPixmap(Pixmap pixmap, HDC hdc, BOOL bDeletePixmap)
5931 HBITMAP hBmp = 0;
5932 BITMAPOBJ *pBmp = NULL;
5933 HGLOBAL hPackedDIB = 0;
5935 /* Allocates an HBITMAP which references the Pixmap passed to us */
5936 hBmp = X11DRV_BITMAP_CreateBitmapHeaderFromPixmap(pixmap);
5937 if (!hBmp)
5939 TRACE("\tCould not create bitmap header for Pixmap\n");
5940 goto END;
5944 * Create a packed DIB from the Pixmap wrapper bitmap created above.
5945 * A packed DIB contains a BITMAPINFO structure followed immediately by
5946 * an optional color palette and the pixel data.
5948 hPackedDIB = DIB_CreateDIBFromBitmap(hdc, hBmp);
5950 /* Get a pointer to the BITMAPOBJ structure */
5951 pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
5953 /* We can now get rid of the HBITMAP wrapper we created earlier.
5954 * Note: Simply calling DeleteObject will free the embedded Pixmap as well.
5956 if (!bDeletePixmap)
5958 /* Clear the physBitmap to prevent the Pixmap from being deleted by DeleteObject */
5959 pBmp->physBitmap = NULL;
5960 pBmp->funcs = NULL;
5962 GDI_ReleaseObj( hBmp );
5963 DeleteObject(hBmp);
5965 END:
5966 TRACE("\tReturning packed DIB %x\n", hPackedDIB);
5967 return hPackedDIB;
5971 /**************************************************************************
5972 * X11DRV_DIB_CreatePixmapFromDIB
5974 * Creates a Pixmap from a packed DIB
5976 Pixmap X11DRV_DIB_CreatePixmapFromDIB( HGLOBAL hPackedDIB, HDC hdc )
5978 Pixmap pixmap = None;
5979 HBITMAP hBmp = 0;
5980 BITMAPOBJ *pBmp = NULL;
5981 LPBYTE pPackedDIB = NULL;
5982 LPBITMAPINFO pbmi = NULL;
5983 LPBITMAPINFOHEADER pbmiHeader = NULL;
5984 LPBYTE pbits = NULL;
5986 /* Get a pointer to the packed DIB's data */
5987 pPackedDIB = (LPBYTE)GlobalLock(hPackedDIB);
5988 pbmiHeader = (LPBITMAPINFOHEADER)pPackedDIB;
5989 pbmi = (LPBITMAPINFO)pPackedDIB;
5990 pbits = (LPBYTE)(pPackedDIB
5991 + DIB_BitmapInfoSize( (LPBITMAPINFO)pbmiHeader, DIB_RGB_COLORS ));
5993 /* Create a DDB from the DIB */
5995 hBmp = CreateDIBitmap(hdc,
5996 pbmiHeader,
5997 CBM_INIT,
5998 (LPVOID)pbits,
5999 pbmi,
6000 DIB_RGB_COLORS);
6002 GlobalUnlock(hPackedDIB);
6004 TRACE("CreateDIBitmap returned %x\n", hBmp);
6006 /* Retrieve the internal Pixmap from the DDB */
6008 pBmp = (BITMAPOBJ *) GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
6010 pixmap = (Pixmap)pBmp->physBitmap;
6011 /* clear the physBitmap so that we can steal its pixmap */
6012 pBmp->physBitmap = NULL;
6013 pBmp->funcs = NULL;
6015 /* Delete the DDB we created earlier now that we have stolen its pixmap */
6016 GDI_ReleaseObj( hBmp );
6017 DeleteObject(hBmp);
6019 TRACE("\tReturning Pixmap %ld\n", pixmap);
6020 return pixmap;