source: trunk/src/gdi32/blit.cpp

Last change on this file was 10558, checked in by sandervl, 21 years ago

CreateDIBitmap: added workaround for DIB_PAL_COLORS mode

File size: 25.8 KB
RevLine 
[10558]1/* $Id: blit.cpp,v 1.51 2004-03-24 16:55:35 sandervl Exp $ */
[2592]2
3/*
4 * GDI32 blit code
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998 Patrick Haller
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
[10495]12#include <stdio.h>
[2592]13#include <os2win.h>
14#include <stdlib.h>
15#include <stdarg.h>
16#include <string.h>
[2614]17#include <cpuhlp.h>
[9576]18#include <winuser32.h>
19#include <dbglog.h>
[10373]20#include "oslibgpi.h"
21#include <dcdata.h>
[2592]22#include "dibsect.h"
[2614]23#include "rgbcvt.h"
[2592]24
[2802]25#define DBG_LOCALLOG DBG_blit
26#include "dbglocal.h"
27
[2592]28static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr);
[5901]29ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy);
[2592]30
[10495]31#ifdef DEBUG
32void dumpBitmapBytes (char *name, int width, int height, char *bits)
33{
34 int i;
35 char buf[4096];
36 char *p = &buf[0];
37
38 dprintf(("%s:\n", name));
39
40 for (i = 0; i < width * height; i++)
41 {
42 if (i % width == 0)
43 {
44 if (i > 0)
45 {
46 dprintf(("%s\n", buf));
47 p = &buf[0];
48 }
49
50 sprintf(p, "%2.2d:", i / width);
51 p += strlen (p);
52 }
53
54 sprintf(p, " %2.2x", bits[i]);
55 p += strlen (p);
56 }
57
58 dprintf(("%s\n", buf));
59}
60#else
61#define dumpBitmapBytes(a, b, c)
62#endif
[2592]63//******************************************************************************
64//******************************************************************************
65BOOL WIN32API StretchBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest,
[3527]66 int nWidthDest, int nHeightDest,
67 HDC hdcSrc, int nXOriginSrc, int nYOriginSrc,
68 int nWidthSrc, int nHeightSrc, DWORD dwRop)
[2592]69{
[8871]70 BOOL rc;
[2592]71
[8871]72 dprintf(("GDI32: StretchBlt Dest: %x (%d, %d) size (%d, %d) ROP %x",
73 hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, dwRop));
74 dprintf(("GDI32: StretchBlt Src : %x (%d, %d) size (%d, %d)\n",
75 hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc));
[7717]76
[8871]77 SetLastError(ERROR_SUCCESS);
78 if(DIBSection::getSection() != NULL)
[2592]79 {
[8871]80 DIBSection *dsect = DIBSection::findHDC(hdcSrc);
81 if(dsect)
82 {
83 rc = dsect->BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
84 nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, dwRop);
[10373]85 goto blitdone;
[8871]86 }
[2592]87 }
[8871]88 rc = O32_StretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, dwRop);
[10373]89
90blitdone:
91 DIBSECTION_MARK_INVALID(hdcDest);
92
[8871]93 if(rc == FALSE) {
94 dprintf(("!WARNING!: GDI32: StretchBlt returned FALSE; last error %x", rc, GetLastError()));
95 }
96 return rc;
[2592]97}
98//******************************************************************************
99//******************************************************************************
[4356]100BOOL WIN32API BitBlt(HDC hdcDest,
101 int nXDest,
102 int nYDest,
103 int nWidth,
104 int nHeight,
105 HDC hdcSrc,
106 int nXSrc,
107 int nYSrc,
108 DWORD dwRop)
[2592]109{
[8871]110 BOOL rc;
[2592]111
[8871]112#ifdef DEBUG
[10373]113 POINT point1, point2;
[8871]114 GetViewportOrgEx(hdcDest, &point1);
115 GetViewportOrgEx(hdcSrc, &point2);
116 dprintf(("BitBlt: Viewport origin dest (%d,%d) src (%d,%d)", point1.x, point1.y, point2.x, point2.y));
117#endif
[7717]118
[8871]119 SetLastError(ERROR_SUCCESS);
120 if(DIBSection::getSection() != NULL)
[4356]121 {
[8871]122 DIBSection *dsect = DIBSection::findHDC(hdcSrc);
123 if(dsect)
124 {
[10373]125 rc = dsect->BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, nXSrc, nYSrc, nWidth, nHeight, dwRop);
126 goto blitdone;
[8871]127 }
[2592]128 }
[8871]129 dprintf(("GDI32: BitBlt to hdc %X from hdc %x (%d,%d) to (%d,%d), (%d,%d) rop %X\n",
130 hdcDest, hdcSrc, nXSrc, nYSrc, nXDest, nYDest, nWidth, nHeight, dwRop));
[7713]131
[8871]132 rc = O32_BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop);
[7713]133
[10373]134blitdone:
135 DIBSECTION_MARK_INVALID(hdcDest);
[8871]136 return rc;
[2592]137}
138//******************************************************************************
139//******************************************************************************
[5677]140static INT SetDIBitsToDevice_(HDC hdc, INT xDest, INT yDest, DWORD cx,
[2602]141 DWORD cy, INT xSrc, INT ySrc,
142 UINT startscan, UINT lines, LPCVOID bits,
[2592]143 const BITMAPINFO *info, UINT coloruse)
144{
[10486]145 INT result, imgsize, palsize;
[2592]146 char *ptr;
[4963]147 ULONG compression = 0, bmpsize;
[5689]148 WORD *newbits = NULL;
149 DWORD bitfields[3];
[2592]150
[4533]151 dprintf(("GDI32: SetDIBitsToDevice hdc:%X xDest:%d yDest:%d, cx:%d, cy:%d, xSrc:%d, ySrc:%d, startscan:%d, lines:%d \nGDI32: bits 0x%X, info 0x%X, coloruse %d",
152 hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (LPVOID) bits, (PBITMAPINFO)info, coloruse));
153
[2808]154 //SvL: RP7's bitmap size is not correct; fix it here or else
155 // the blit is messed up in Open32
[5689]156 imgsize = CalcBitmapSize(info->bmiHeader.biBitCount,
157 info->bmiHeader.biWidth, info->bmiHeader.biHeight);
[2808]158 bmpsize = info->bmiHeader.biSizeImage;
[3343]159 if(info->bmiHeader.biCompression == 0 && info->bmiHeader.biSizeImage &&
160 info->bmiHeader.biSizeImage < imgsize)
[2808]161 {
162 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = imgsize;
163 }
164
[5689]165 switch(info->bmiHeader.biBitCount) {
166 case 15:
[5967]167 case 16: //Default if BI_BITFIELDS not set is RGB 555
[8871]168 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : DEFAULT_16BPP_RED_MASK;
169 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : DEFAULT_16BPP_GREEN_MASK;
170 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : DEFAULT_16BPP_BLUE_MASK;
[5689]171 break;
[7327]172
173 case 24:
[5689]174 case 32:
[8871]175 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : DEFAULT_24BPP_RED_MASK;
176 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : DEFAULT_24BPP_GREEN_MASK;
177 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : DEFAULT_24BPP_BLUE_MASK;
[5689]178 break;
179 default:
180 bitfields[0] = 0;
181 bitfields[1] = 0;
182 bitfields[2] = 0;
183 break;
184 }
[5790]185
[10513]186 // GPI will crash when the app accidentally specifies PAL indexes with
187 // high bpp bitmap data
188 if(coloruse == DIB_PAL_COLORS && info->bmiHeader.biBitCount >= 15) {
189 dprintf(("WARNING: DIB_PAL_COLORS can't be used for high color bitmaps!!"));
190 coloruse = DIB_RGB_COLORS;
191 }
192
[5689]193 if(bitfields[1] == 0x3E0)
194 {//RGB 555?
[5690]195 dprintf(("RGB 555->565 conversion required %x %x %x", bitfields[0], bitfields[1], bitfields[2]));
[5689]196
197 newbits = (WORD *)malloc(imgsize);
[10167]198 pRGB555to565(newbits, (WORD *)bits, imgsize/sizeof(WORD));
[5689]199 bits = newbits;
[10513]200 dprintf(("RGB 555->565 new bits %x", newbits));
[5689]201 }
202
[2592]203 //SvL: Ignore BI_BITFIELDS type (SetDIBitsToDevice fails otherwise)
[2600]204 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
[2602]205 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
206 compression = BI_BITFIELDS;
[2600]207 }
[4968]208 if(startscan != 0 || lines != info->bmiHeader.biHeight) {
[10373]209 dprintf(("WARNING: SetDIBitsToDevice startscan != 0 || lines != info->bmiHeader.biHeight"));
[7791]210 dprintf(("info bmp (%d,%d)", info->bmiHeader.biWidth, info->bmiHeader.biHeight));
[4968]211 }
212
[4963]213 result = O32_StretchDIBits(hdc, xDest, yDest, cx, cy, xSrc, ySrc,
[4968]214 cx, cy, (void *)bits,
[4963]215 (PBITMAPINFO)info, coloruse, SRCCOPY);
216
217 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
218 if(result != info->bmiHeader.biHeight) {
[8871]219 dprintf(("SetDIBitsToDevice failed with rc %x", result));
[2614]220 }
[4963]221 else
222 {
223 result = info->bmiHeader.biHeight;
[2592]224
[10373]225 DIBSECTION_MARK_INVALID(hdc);
[4963]226 }
[2808]227 dprintf(("GDI32: SetDIBitsToDevice hdc:%X xDest:%d yDest:%d, cx:%d, cy:%d, xSrc:%d, ySrc:%d, startscan:%d, lines:%d \nGDI32: bits 0x%X, info 0x%X, coloruse %d returned %d",
[10373]228 hdc, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, (LPVOID) bits, (PBITMAPINFO)info, coloruse, result));
[2592]229 dprintf(("GDI32: SetDIBitsToDevice %d %d %d %d %x %d", info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biPlanes, info->bmiHeader.biBitCount, info->bmiHeader.biCompression, info->bmiHeader.biSizeImage));
230
[2600]231 if(compression == BI_BITFIELDS) {
[2602]232 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
[2600]233 }
[5689]234 if(newbits) free(newbits);
[8871]235
[2808]236 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = bmpsize;
[2592]237 return result;
238}
239//******************************************************************************
240//******************************************************************************
[10495]241//always extract actual bits to be drawn and construct new bitmap before
242//calling O32_* API if only part of bitmap is drawn
[5677]243INT WIN32API SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
244 DWORD cy, INT xSrc, INT ySrc,
245 UINT startscan, UINT lines, LPCVOID bits,
246 const BITMAPINFO *info, UINT coloruse)
247{
[10486]248 INT height, width;
249 INT rc = 0;
[7327]250 char *newBits = NULL;
251
[10495]252 // save a copy of header as it will be changed probably
253 BITMAPINFOHEADER originalHeader = info->bmiHeader;
254
255 SetLastError(ERROR_SUCCESS);
[9576]256
[10486]257 if(info == NULL) {
258 goto invalid_parameter;
259 }
[10495]260
[10558]261 dprintf(("BITMAP: (%d,%d) %d bpp %d bytes",
262 info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biBitCount, info->bmiHeader.biSizeImage));
[10495]263
[10486]264 height = info->bmiHeader.biHeight;
265 width = info->bmiHeader.biWidth;
266
267 if (height < 0) height = -height;
[10495]268
[10486]269 if (!lines || (startscan >= height)) {
270 goto invalid_parameter;
271 }
[10495]272
[10486]273 if (startscan + lines > height) lines = height - startscan;
274
[10495]275 if (ySrc < startscan) { cy -= startscan - ySrc; ySrc = startscan; }
[10486]276 else if (ySrc >= startscan + lines) goto invalid_parameter;
277
278 if (xSrc >= width) goto invalid_parameter;
279
280 if (ySrc + cy >= startscan + lines) cy = startscan + lines - ySrc;
281
282 if (xSrc + cx >= width) cx = width - xSrc;
283
284 if (!cx || !cy) goto invalid_parameter;
285
[10495]286 // check if new bitmap must be created
287 if (xSrc == 0 && ySrc == 0 && startscan == 0 && lines == height &&
288 cx == width && cy == height && info->bmiHeader.biHeight > 0)
289 {
290 // bitmap is ok and can be drawn directly
291 }
292 else
293 {
294 // create new bits if we know the bits format
295 if (info->bmiHeader.biCompression == BI_RGB ||
296 info->bmiHeader.biCompression == BI_BITFIELDS)
297 {
[10497]298 // not zero if bpp < 8 and starting on an uneven pixel
299 UINT xOffset = (xSrc * info->bmiHeader.biBitCount) % 8;
300
[10495]301 // compute size of memory buffer
302 UINT lBytesPerLineOrig = DIB_GetDIBWidthBytes (info->bmiHeader.biWidth, info->bmiHeader.biBitCount);
[10497]303 UINT lBytesToCopyInLine = DIB_GetDIBWidthBytes (cx + xOffset, info->bmiHeader.biBitCount);
[10495]304
305 newBits = (char *)malloc (lBytesToCopyInLine * cy);
306
307 if (newBits)
308 {
309 // copy bits to new buffer
310 int i;
[10497]311
312 char *pNewBits = (char *)newBits;
313
[10495]314 if (info->bmiHeader.biHeight > 0)
315 {
[10497]316 // starting pointer
317 char *pBits = (char *)bits + // origin
318 (ySrc - startscan) * lBytesPerLineOrig + // y offset
319 (xSrc * info->bmiHeader.biBitCount) / 8; // x offset
320
[10495]321 for (i = 0; i < cy; i++)
322 {
323 memcpy (pNewBits, pBits, lBytesToCopyInLine);
324 pBits += lBytesPerLineOrig;
325 pNewBits += lBytesToCopyInLine;
326 }
327 }
328 else
329 {
[10497]330 // starting pointer
331 char *pBits = (char *)bits + // origin
332 (lines - 1 - (ySrc - startscan)) * lBytesPerLineOrig + // y offset
333 (xSrc * info->bmiHeader.biBitCount) / 8; // x offset
334
[10495]335 for (i = 0; i < cy; i++)
336 {
337 memcpy (pNewBits, pBits, lBytesToCopyInLine);
[10497]338 pBits -= lBytesPerLineOrig;
339 pNewBits += lBytesToCopyInLine;
[10495]340 }
341 }
342
343 // newBits contain partial bitmap, correct the header
344 // todo bitcount < 8
[10497]345 ((BITMAPINFO *)info)->bmiHeader.biWidth = cx + xOffset;
[10495]346 ((BITMAPINFO *)info)->bmiHeader.biHeight = cy;
347 ((BITMAPINFO *)info)->bmiHeader.biSizeImage = lBytesToCopyInLine * cy;
348
349 ySrc = startscan = 0;
[10497]350 xSrc = xOffset;
[10495]351 lines = cy;
[10497]352 dprintf(("Converted BITMAP: (%d,%d) %d bytes xSrc %d ySrc %d",
353 info->bmiHeader.biWidth, info->bmiHeader.biHeight, info->bmiHeader.biSizeImage, xSrc, ySrc));
[5677]354 }
355 }
356 }
[10495]357
358 // draw bits
359 rc = SetDIBitsToDevice_( hdc, xDest, yDest,
360 cx, cy, xSrc, ySrc, startscan, lines,
361 newBits? newBits: bits, info, coloruse );
362
363 if (newBits)
364 {
365 // restore original header
366 *(BITMAPINFOHEADER *)&info->bmiHeader = originalHeader;
367 free (newBits);
368 }
369
[7327]370 return rc;
[10486]371
372invalid_parameter:
373 SetLastError(ERROR_INVALID_PARAMETER);
374 return 0;
[5677]375}
376//******************************************************************************
377//******************************************************************************
[2592]378BOOL WIN32API PatBlt(HDC hdc,int nXLeft,int nYLeft,int nWidth,int nHeight,DWORD dwRop)
379{
[8871]380 BOOL rc;
[2592]381
[8871]382 dprintf(("PatBlt %x (%d,%d)(%d,%d) %x", hdc, nXLeft,nYLeft,nWidth,nHeight, dwRop));
383 //CB: Open32 bug: negative width/height not supported!
384 if (nWidth < 0)
385 {
386 nXLeft += nWidth+1;
387 nWidth = -nWidth;
388 }
389 if (nHeight < 0)
390 {
391 nYLeft += nHeight+1;
392 nHeight = -nHeight;
393 }
394 rc = O32_PatBlt(hdc,nXLeft,nYLeft,nWidth,nHeight,dwRop);
395 if(rc) {
[10373]396 DIBSECTION_MARK_INVALID(hdc);
[8871]397 }
398 return(rc);
[2592]399}
400//******************************************************************************
401//******************************************************************************
[10373]402BOOL WIN32API MaskBlt( HDC hdcDest, int arg2, int arg3, int arg4, int arg5, HDC hdcSrc, int arg7, int arg8, HBITMAP arg9, int arg10, int arg11, DWORD arg12)
[2592]403{
[10373]404 BOOL ret;
405
406 DIBSECTION_CHECK_IF_DIRTY(hdcSrc);
407
408 ret = O32_MaskBlt(hdcDest, arg2, arg3, arg4, arg5, hdcSrc, arg7, arg8, arg9, arg10, arg11, arg12);
409 if(ret) {
410 DIBSECTION_MARK_INVALID(hdcDest);
411 }
412 return ret;
[2592]413}
414//******************************************************************************
415//******************************************************************************
416BOOL WIN32API PlgBlt(HDC hdcDest, CONST POINT *lpPoint, HDC hdcSrc, int nXSrc,
[3726]417 int nYSrc, int nWidth, int nHeight, HBITMAP hbmMask,
418 int xMast, int yMask)
[2592]419{
[8871]420 dprintf(("GDI32: PlgBlt, not implemented\n"));
421 return(FALSE);
[2592]422}
423//******************************************************************************
424//******************************************************************************
[5690]425static INT StretchDIBits_(HDC hdc, INT xDst, INT yDst, INT widthDst,
[3589]426 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
427 INT heightSrc, const void *bits,
428 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
429{
[8871]430 INT rc;
431 DWORD bitfields[3], compression = 0;
432 WORD *newbits = NULL;
[3589]433
434 dprintf(("GDI32: StretchDIBits %x to (%d,%d) (%d,%d) from (%d,%d) (%d,%d), %x %x %x %x", hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, bits, info, wUsage, dwRop));
435
[4676]436 if(info->bmiHeader.biBitCount == 1) {
437 dprintf(("WARNING: StretchDIBits does NOT work correctly for 1 bpp bitmaps!!"));
438 }
[10486]439#if 0
440 // SvL: I'm not sure what this was supposed to fix, but it breaks one
441 // application here
442 // SetDIBitsToDevice works with palette indexes, so this should not
443 // be necessary (anymore)
[3589]444 if(wUsage == DIB_PAL_COLORS && info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
445 {
446 // workaround for open32 bug.
447 // If syscolors > 256 and wUsage == DIB_PAL_COLORS.
448
449 int i;
[10486]450 UINT biClrUsed;
[3589]451 USHORT *pColorIndex = (USHORT *)info->bmiColors;
[10486]452 RGBQUAD *pColors;
453 BITMAPINFO *infoLoc;
[3589]454
[10486]455 biClrUsed = (info->bmiHeader.biClrUsed) ? info->bmiHeader.biClrUsed : (1<<info->bmiHeader.biBitCount);
456
457 pColors = (RGBQUAD *) alloca(biClrUsed * sizeof(RGBQUAD));
458 infoLoc = (BITMAPINFO *) alloca(sizeof(BITMAPINFO) + biClrUsed * sizeof(RGBQUAD));
459
[3589]460 memcpy(infoLoc, info, sizeof(BITMAPINFO));
461
[10486]462 if(GetDIBColorTable(hdc, 0, biClrUsed, pColors) == 0)
463 {
464 dprintf(("ERROR: StretchDIBits: GetDIBColorTable failed!!"));
465 return FALSE;
[4034]466 }
[10486]467 for(i=0;i<biClrUsed;i++, pColorIndex++)
[3589]468 {
[10486]469 infoLoc->bmiColors[i] = pColors[*pColorIndex];
[3589]470 }
471
472 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
473 widthSrc, heightSrc, (void *)bits,
474 (PBITMAPINFO)infoLoc, DIB_RGB_COLORS, dwRop);
475
[4254]476 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
477 if(rc != heightSrc && rc != infoLoc->bmiHeader.biHeight) {
[10373]478 dprintf(("StretchDIBits failed with rc %x", rc));
[3589]479 }
[10373]480 else {
481 rc = heightSrc;
[4254]482
[10373]483 DIBSECTION_MARK_INVALID(hdc);
484 }
[8871]485
486 return rc;
[3589]487 }
[10486]488#endif
[5870]489 switch(info->bmiHeader.biBitCount) {
490 case 15:
[5967]491 case 16: //Default if BI_BITFIELDS not set is RGB 555
[8871]492 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : DEFAULT_16BPP_RED_MASK;
493 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : DEFAULT_16BPP_GREEN_MASK;
494 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : DEFAULT_16BPP_BLUE_MASK;
[5870]495 break;
[7327]496 case 24:
[5870]497 case 32:
[8871]498 bitfields[0] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *(DWORD *)info->bmiColors : DEFAULT_24BPP_RED_MASK;
499 bitfields[1] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 1) : DEFAULT_24BPP_GREEN_MASK;
500 bitfields[2] = (info->bmiHeader.biCompression == BI_BITFIELDS) ? *((DWORD *)info->bmiColors + 2) : DEFAULT_24BPP_BLUE_MASK;
[5870]501 break;
502 default:
503 bitfields[0] = 0;
504 bitfields[1] = 0;
505 bitfields[2] = 0;
506 break;
507 }
[10167]508
[10513]509 // GPI will crash when the app accidentally specifies PAL indexes with
510 // high bpp bitmap data
511 if(wUsage == DIB_PAL_COLORS && info->bmiHeader.biBitCount >= 15) {
512 dprintf(("WARNING: DIB_PAL_COLORS can't be used for high color bitmaps!!"));
513 wUsage = DIB_RGB_COLORS;
514 }
515
[8871]516 if(bitfields[1] == RGB555_GREEN_MASK)
[5870]517 {//RGB 555?
518 dprintf(("RGB 555->565 conversion required %x %x %x", bitfields[0], bitfields[1], bitfields[2]));
519
[9355]520 ULONG imgsize = CalcBitmapSize(info->bmiHeader.biBitCount,
[10167]521 abs(info->bmiHeader.biWidth), heightSrc);
[9355]522 ULONG offset = CalcBitmapSize(info->bmiHeader.biBitCount,
[10167]523 abs(info->bmiHeader.biWidth), ySrc)/sizeof(WORD);
[9355]524 newbits = (WORD *) HeapAlloc(GetProcessHeap(), 0, imgsize);
[10167]525
526 //we still convert too much
527 pRGB555to565(newbits, (WORD *)bits+offset, imgsize/sizeof(WORD));
[5870]528 bits = newbits;
[10167]529
530 ySrc = 0;
[5870]531 }
[9429]532 //SvL: Ignore BI_BITFIELDS type (StretchDIBits fails otherwise)
[6692]533 if(info->bmiHeader.biCompression == BI_BITFIELDS) {
534 ((BITMAPINFO *)info)->bmiHeader.biCompression = 0;
535 compression = BI_BITFIELDS;
536 }
537
[3589]538 rc = O32_StretchDIBits(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc,
[10373]539 widthSrc, heightSrc, (void *)bits,
540 (PBITMAPINFO)info, wUsage, dwRop);
[5870]541
[6692]542 if(compression == BI_BITFIELDS) {
543 ((BITMAPINFO *)info)->bmiHeader.biCompression = BI_BITFIELDS;
544 }
[9355]545 if(newbits) HeapFree(GetProcessHeap(), 0, newbits);
[5870]546
[4254]547 //Open32 always returns height of bitmap (regardless of how many scanlines were copied)
548 if(rc != heightSrc && rc != info->bmiHeader.biHeight) {
[8871]549 dprintf(("StretchDIBits failed with rc %x", rc));
[3589]550 }
[4254]551 else
552 {
[8871]553 rc = heightSrc;
[4254]554
[10373]555 DIBSECTION_MARK_INVALID(hdc);
[3589]556 }
557
558 return rc;
559}
560//******************************************************************************
561//******************************************************************************
[5690]562INT WIN32API StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst,
563 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
564 INT heightSrc, const void *bits,
565 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
566{
567 if(info->bmiHeader.biHeight < 0) {
568 // upside down
569 INT rc = 0;
570 BITMAPINFO newInfo;
571 newInfo.bmiHeader = info->bmiHeader;
572 long lLineByte = ((newInfo.bmiHeader.biWidth * (info->bmiHeader.biBitCount == 15 ? 16 : info->bmiHeader.biBitCount) + 31) / 32) * 4;
573 long lHeight = -newInfo.bmiHeader.biHeight;
574 newInfo.bmiHeader.biHeight = -newInfo.bmiHeader.biHeight;
575
[6319]576 //TODO: doesn't work if memory is readonly!!
577 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
578
[5690]579 char *newBits = (char *)malloc( lLineByte * lHeight );
580 if(newBits) {
581 unsigned char *pbSrc = (unsigned char *)bits + lLineByte * (lHeight - 1);
582 unsigned char *pbDst = (unsigned char *)newBits;
583 for(int y = 0; y < lHeight; y++) {
584 memcpy( pbDst, pbSrc, lLineByte );
585 pbDst += lLineByte;
586 pbSrc -= lLineByte;
587 }
588 rc = StretchDIBits_(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, newBits, info, wUsage, dwRop);
589 free( newBits );
590 }
[6319]591
592 //TODO: doesn't work if memory is readonly!!
593 ((BITMAPINFO *)info)->bmiHeader.biHeight = -info->bmiHeader.biHeight;
[5690]594 return rc;
595 } else {
596 return StretchDIBits_(hdc, xDst, yDst, widthDst, heightDst, xSrc, ySrc, widthSrc, heightSrc, bits, info, wUsage, dwRop);
597 }
598}
599//******************************************************************************
600//******************************************************************************
[2592]601int WIN32API SetStretchBltMode( HDC arg1, int arg2)
602{
[10373]603#ifdef DEBUG
[8871]604 if(DIBSection::getSection() != NULL)
[2592]605 {
[8871]606 DIBSection *dsect = DIBSection::findHDC(arg1);
607 if(dsect)
608 {
609 dprintf((" - DC is DIBSection\n"));
610 }
[2592]611 }
[10373]612#endif
[8871]613 return O32_SetStretchBltMode(arg1, arg2);
[2592]614}
615//******************************************************************************
616//******************************************************************************
617int WIN32API GetStretchBltMode( HDC arg1)
618{
619 return O32_GetStretchBltMode(arg1);
620}
621//******************************************************************************
622//******************************************************************************
623static ULONG QueryPaletteSize(BITMAPINFOHEADER *pBHdr)
624{
625 ULONG cbPalette;
626
627 switch (pBHdr->biBitCount)
628 {
629 case 1:
630 case 4:
631 case 8:
632 cbPalette = (1 << pBHdr->biBitCount) * sizeof(RGBQUAD);
633 break;
634
635 case 16:
636 case 24:
637 case 32:
638 cbPalette = 0;
639 break;
640
641 default:
642 dprintf(("QueryPaletteSize: error pBHdr->biBitCount = %d", pBHdr->biBitCount));
643 cbPalette = -1;
644 }
645
646 return cbPalette;
647}
648//******************************************************************************
649//******************************************************************************
[5901]650ULONG CalcBitmapSize(ULONG cBits, LONG cx, LONG cy)
[2592]651{
652 ULONG alignment;
653 ULONG factor;
654 BOOL flag = TRUE; //true: '*' false: '/'
655
656 cy = cy < 0 ? -cy : cy;
657
658 switch(cBits)
659 {
660 case 1:
661 factor = 8;
662 flag = FALSE;
663 break;
664
665 case 4:
666 factor = 2;
667 flag = FALSE;
668 break;
669
670 case 8:
671 factor = 1;
672 break;
673
674 case 16:
675 factor = 2;
676 break;
677
678 case 24:
679 factor = 3;
680 break;
681
682 case 32:
[7327]683 return cx*cy*4;
[2592]684
685 default:
686 return 0;
687 }
688
689 if (flag)
690 alignment = (cx = (cx*factor)) % 4;
691 else
692 alignment = (cx = ((cx+factor-1)/factor)) % 4;
693
694 if (alignment != 0)
695 cx += 4 - alignment;
696
697 return cx*cy;
698}
699//******************************************************************************
700//******************************************************************************
Note: See TracBrowser for help on using the repository browser.