2 * DIB Engine DIBDRVBITMAP handling
4 * Copyright 2009 Massimo Del Fedele
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv
);
28 /* gets human-readable dib format name */
29 const char *_DIBDRVBITMAP_GetFormatName(DIBDRVBITMAP
const *bmp
)
34 return "NULL BITMAP DETECTED";
43 return "DIBFMT_DIB4_RLE";
47 return "DIBFMT_DIB8_RLE";
48 case DIBFMT_DIB16_RGB
:
49 return "DIBFMT_DIB_RGB";
50 case DIBFMT_DIB16_BITFIELDS
:
51 return "DIBFMT_DIB16_BITFIELDS";
53 return "DIBFMT_DIB24";
54 case DIBFMT_DIB32_RGB
:
55 return "DIBFMT_DIB32_RGB";
56 case DIBFMT_DIB32_BITFIELDS
:
57 return "DIBFMT_DIB32_BITFIELDS";
60 return "DIBFMT_UNKNOWN";
64 /* calculates shift and length given a bit mask */
65 static void CalcShiftAndLen(DWORD mask
, int *shift
, int *len
)
72 FIXME("color mask == 0 -- problem on init_dib\n");
78 /* calculates bit shift
79 (number of 0's on right of bit field */
81 while ((mask
& 1) == 0)
87 /* calculates bitfield length
88 (number of 1's in bit field */
90 while ((mask
& 1) == 1)
99 /* initializes bit fields from bit masks */
100 static void InitBitFields(DIBDRVBITMAP
*dib
, const DWORD
*bit_fields
)
102 dib
->redMask
= bit_fields
[0];
103 dib
->greenMask
= bit_fields
[1];
104 dib
->blueMask
= bit_fields
[2];
105 CalcShiftAndLen(dib
->redMask
, &dib
->redShift
, &dib
->redLen
);
106 CalcShiftAndLen(dib
->greenMask
, &dib
->greenShift
, &dib
->greenLen
);
107 CalcShiftAndLen(dib
->blueMask
, &dib
->blueShift
, &dib
->blueLen
);
110 /* sets/gets bits of a DIBDRVBITMAP taking in account if it's a top down
111 or a bottom-up DIB */
112 void _DIBDRVBITMAP_Set_Bits(DIBDRVBITMAP
*dib
, void *bits
, BOOL owns
)
114 /* checks whether dib is top-down or bottom-up one */
123 /* data->bits always points to the top-left corner and the stride is -ve */
124 dib
->bits
= (BYTE
*)bits
- (dib
->height
- 1) * dib
->stride
;
126 dib
->ownsBits
= owns
;
129 void *_DIBDRVBITMAP_Get_Bits(DIBDRVBITMAP
* dib
)
131 /* checks whether dib is top-down or bottom-up one */
140 /* data->bits always points to the top-left corner and the stride is -ve */
141 return (BYTE
*)dib
->bits
+ (dib
->height
- 1) * dib
->stride
;
145 /* calculates and sets the lightest color for monochrome bitmaps */
146 int _DIBDRVBITMAP_GetLightestColorIndex(DIBDRVBITMAP
*dib
)
148 DWORD foreRed
, foreGreen
, foreBlue
;
149 DWORD backRed
, backGreen
, backBlue
;
150 RGBQUAD
*fore
, *back
;
152 /* zero for non-monochrome bitmaps */
153 if(dib
->bitCount
!= 1)
155 /* just in case color table hasn't been grabbed yet */
156 if(!dib
->colorTableGrabbed
)
158 back
= dib
->colorTable
;
160 foreRed
= fore
->rgbRed
; foreGreen
= fore
->rgbGreen
; foreBlue
= fore
->rgbBlue
;
161 backRed
= back
->rgbRed
; backGreen
= back
->rgbGreen
; backBlue
= back
->rgbBlue
;
162 if(foreRed
*foreRed
+ foreGreen
*foreGreen
+ foreBlue
*foreBlue
>
163 backRed
*backRed
+ backGreen
*backGreen
+ backBlue
*backBlue
)
172 /* initializes dib from a bitmap :
173 dib dib being initialized
174 bi source BITMAPINFOHEADER with required DIB format info
175 bit_fields color masks
176 colorTable color table, if any
177 bits pointer to image data array
178 NOTE : DIBDRVBITMAP doesn't owns bits, but do own color table
180 BOOL
_DIBDRVBITMAP_InitFromBMIH(DIBDRVBITMAP
*dib
, const BITMAPINFOHEADER
*bi
, const DWORD
*bit_fields
,
181 const RGBQUAD
*colorTable
, void *bits
)
183 MAYBE(TRACE("dib=%p, bi=%p, bit_fields=%p, colorTable=%p, bits=%p\n", dib
, bi
, bit_fields
, colorTable
, bits
));
185 /* initializes DIB dimensions and color depth */
186 dib
->bitCount
= bi
->biBitCount
;
187 dib
->width
= bi
->biWidth
;
188 dib
->height
= bi
->biHeight
;
189 dib
->stride
= ((dib
->width
* dib
->bitCount
+ 31) >> 3) & ~3;
191 /* initializes image data pointer */
193 dib
->ownsBits
= FALSE
;
195 /* initializes color table */
196 dib
->colorTableSize
= 0;
197 dib
->colorTable
= NULL
;
198 dib
->colorTableGrabbed
= FALSE
;
200 /* checks whether dib is top-down or bottom-up one */
204 dib
->height
= -dib
->height
;
210 /* data->bits always points to the top-left corner and the stride is -ve */
211 dib
->bits
= (BYTE
*)dib
->bits
+ (dib
->height
- 1) * dib
->stride
;
212 dib
->stride
= -dib
->stride
;
213 dib
->topdown
= FALSE
;
216 /* gets and stores bitmap format */
217 switch(dib
->bitCount
)
220 dib
->format
= DIBFMT_DIB24
;
221 dib
->funcs
= &DIBDRV_funcs_DIB24
;
226 if(bi
->biCompression
== BI_RGB
)
228 dib
->format
= DIBFMT_DIB32_RGB
;
229 dib
->funcs
= &DIBDRV_funcs_DIB32_RGB
;
233 InitBitFields(dib
, bit_fields
);
234 dib
->format
= DIBFMT_DIB32_BITFIELDS
;
235 dib
->funcs
= &DIBDRV_funcs_DIB32_BITFIELDS
;
240 if(bi
->biCompression
== BI_RGB
)
242 dib
->format
= DIBFMT_DIB16_RGB
;
243 dib
->funcs
= &DIBDRV_funcs_DIB16_RGB
;
247 InitBitFields(dib
, bit_fields
);
248 dib
->format
= DIBFMT_DIB16_BITFIELDS
;
249 dib
->funcs
= &DIBDRV_funcs_DIB16_BITFIELDS
;
254 dib
->format
= DIBFMT_DIB8
;
255 dib
->funcs
= &DIBDRV_funcs_DIB8
;
256 dib
->colorTableSize
= 256;
257 if(bi
->biClrUsed
) dib
->colorTableSize
= bi
->biClrUsed
;
261 dib
->format
= DIBFMT_DIB4
;
262 dib
->funcs
= &DIBDRV_funcs_DIB4
;
263 dib
->colorTableSize
= 16;
264 if(bi
->biClrUsed
) dib
->colorTableSize
= bi
->biClrUsed
;
268 dib
->format
= DIBFMT_DIB1
;
269 dib
->funcs
= &DIBDRV_funcs_DIB1
;
270 dib
->colorTableSize
= 2;
271 if(bi
->biClrUsed
) dib
->colorTableSize
= bi
->biClrUsed
;
275 dib
->format
= DIBFMT_UNKNOWN
;
277 FIXME("bpp %d not supported\n", dib
->bitCount
);
280 MAYBE(TRACE("DIB FORMAT : %s\n", _DIBDRVBITMAP_GetFormatName(dib
)));
282 /* allocates color table and copy it from source, *if* source is
284 if(dib
->colorTableSize
&& colorTable
)
286 if(!(dib
->colorTable
= HeapAlloc(GetProcessHeap(), 0,
287 dib
->colorTableSize
* sizeof(dib
->colorTable
[0]))
290 ERR("HeapAlloc failed\n");
293 memcpy(dib
->colorTable
, colorTable
,
294 dib
->colorTableSize
* sizeof(dib
->colorTable
[0]));
295 dib
->colorTableGrabbed
= TRUE
;
297 /* for monochrome bitmaps, we need the 'lightest' color */
298 _DIBDRVBITMAP_GetLightestColorIndex(dib
);
300 else if(!dib
->colorTableSize
)
301 /* no color table on more than 8 bits/pixel */
302 dib
->colorTableGrabbed
= TRUE
;
304 MAYBE(TRACE("END\n"));
308 DIBDRVBITMAP
*_DIBDRVBITMAP_CreateFromBMIH(const BITMAPINFOHEADER
*bi
, const DWORD
*bit_fields
,
309 const RGBQUAD
*colorTable
, void *bits
)
311 DIBDRVBITMAP
*bmp
= _DIBDRVBITMAP_New();
312 if(bmp
&& !_DIBDRVBITMAP_InitFromBMIH(bmp
, bi
, bit_fields
, colorTable
, bits
))
314 _DIBDRVBITMAP_Free(bmp
);
320 /* gets a BITMAPINFOHEADER from a soure BITMAPINFO- or BITMAPCORE-header */
321 static BITMAPINFOHEADER
*GetBitmapInfoHeader(BITMAPINFO
const *bmi
)
323 BITMAPINFOHEADER
*res
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(BITMAPINFOHEADER
));
325 int size
= bmi
->bmiHeader
.biSize
;
326 if(size
>= sizeof(BITMAPINFOHEADER
))
328 memcpy(res
, bmi
, sizeof(BITMAPINFOHEADER
));
329 res
->biSize
= sizeof(BITMAPINFOHEADER
);
331 else if(size
== sizeof(BITMAPCOREHEADER
))
333 BITMAPCOREHEADER
*core
= (BITMAPCOREHEADER
*)bmi
;
334 res
->biSize
= sizeof(BITMAPINFOHEADER
);
335 res
->biWidth
= core
->bcWidth
;
336 res
->biHeight
= core
->bcHeight
;
337 res
->biPlanes
= core
->bcPlanes
;
338 res
->biBitCount
= core
->bcBitCount
;
342 HeapFree(GetProcessHeap(), 0, res
);
343 ERR("Bad/unknown header size %d\n", size
);
349 BOOL
_DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP
*dib
, const BITMAPINFO
*bmi
, void *bits
)
351 static const DWORD bit_fields_DIB32_RGB
[3] = {0xff0000, 0x00ff00, 0x0000ff};
352 static const DWORD bit_fields_DIB16_RGB
[3] = {0x7c00, 0x03e0, 0x001f};
353 const DWORD
*masks
= NULL
;
354 RGBQUAD
*colorTable
= NULL
;
355 BITMAPINFOHEADER
*bi
;
360 /* gets info header */
361 if(!(bi
= GetBitmapInfoHeader(bmi
)))
364 ptr
= (BYTE
*)bmi
+ bmi
->bmiHeader
.biSize
;
365 num_colors
= bi
->biClrUsed
;
367 MAYBE(TRACE("dib=%p, bmi=%p\n", dib
, bmi
));
369 if(bi
->biCompression
== BI_BITFIELDS
)
371 masks
= (DWORD
*)ptr
;
372 ptr
+= 3 * sizeof(DWORD
);
374 else if(bi
->biBitCount
== 32)
375 masks
= bit_fields_DIB32_RGB
;
376 else if(bi
->biBitCount
== 16)
377 masks
= bit_fields_DIB16_RGB
;
379 if(!num_colors
&& bi
->biBitCount
<= 8)
380 num_colors
= 1 << bi
->biBitCount
;
382 colorTable
= (RGBQUAD
*)ptr
;
383 ptr
+= num_colors
* sizeof(*colorTable
);
385 res
= _DIBDRVBITMAP_InitFromBMIH(dib
, bi
, masks
, colorTable
, bits
? bits
: ptr
);
386 HeapFree(GetProcessHeap(), 0, bi
);
387 MAYBE(TRACE("END\n"));
391 DIBDRVBITMAP
*_DIBDRVBITMAP_CreateFromBitmapinfo(const BITMAPINFO
*bmi
, void *bits
)
393 DIBDRVBITMAP
*bmp
= _DIBDRVBITMAP_New();
394 if(bmp
&& !_DIBDRVBITMAP_InitFromBitmapinfo(bmp
, bmi
, bits
))
396 _DIBDRVBITMAP_Free(bmp
);
402 /* initializes a DIBRDVBITMAP copying it from a source one
404 dib destination DIBDRVBITMAP
405 src source DIBDRVBITMAP
406 copy TRUE->copy source pixel array FALSE->link to source pixel array
408 BOOL
_DIBDRVBITMAP_InitFromDibdrvbitmap(DIBDRVBITMAP
*dib
, const DIBDRVBITMAP
*src
, BOOL copy
)
410 MAYBE(TRACE("dib=%p, src=%p, copy=%d\n", dib
, src
, copy
));
412 dib
->format
= src
->format
;
413 dib
->width
= src
->width
;
414 dib
->height
= src
->height
;
415 dib
->stride
= src
->stride
;
416 dib
->bitCount
= src
->bitCount
;
418 dib
->redMask
= src
->redMask
;
419 dib
->greenMask
= src
->greenMask
;
420 dib
->blueMask
= src
->blueMask
;
421 dib
->redShift
= src
->redShift
;
422 dib
->greenShift
= src
->greenShift
;
423 dib
->blueShift
= src
->blueShift
;
424 dib
->redLen
= src
->redLen
;
425 dib
->greenLen
= src
->greenLen
;
426 dib
->blueLen
= src
->blueLen
;
428 dib
->funcs
= src
->funcs
;
430 dib
->lightColor
= src
->lightColor
;
432 dib
->topdown
= src
->topdown
;
436 int size
= dib
->height
*abs(dib
->stride
);
437 if(!(dib
->bits
= HeapAlloc(GetProcessHeap(), 0, size
)))
439 ERR("Failed to allocate bits buffer\n");
442 dib
->ownsBits
= TRUE
;
444 /* check for bottom-up DIB */
447 /* copy the bitmap array */
448 memcpy(dib
->bits
, (BYTE
*)src
->bits
+ (src
->height
- 1) * src
->stride
, size
);
450 dib
->bits
= (BYTE
*)dib
->bits
- (dib
->height
-1) * dib
->stride
;
454 /* copy the bitmap array */
455 memcpy(dib
->bits
, src
->bits
, size
);
460 dib
->bits
= src
->bits
;
461 dib
->ownsBits
= FALSE
;
466 dib
->colorTable
= HeapAlloc(GetProcessHeap(), 0, src
->colorTableSize
* sizeof(src
->colorTable
[0]));
467 memcpy(dib
->colorTable
, src
->colorTable
, src
->colorTableSize
* sizeof(src
->colorTable
[0]));
470 dib
->colorTable
= NULL
;
471 dib
->colorTableSize
= src
->colorTableSize
;
472 dib
->colorTableGrabbed
= TRUE
;
473 MAYBE(TRACE("END\n"));
478 /* creates a DIBRDVBITMAP copying format info from a source one
480 dib destination DIBDRVBITMAP
481 src source DIBDRVBITMAP
482 widht, height sizes of newly created bitmap
484 BOOL
_DIBDRVBITMAP_CreateFromDibdrvbitmap(DIBDRVBITMAP
*dib
, const DIBDRVBITMAP
*src
, int width
, int height
)
486 MAYBE(TRACE("dib=%p, src=%p, width=%d, height=%d\n", dib
, src
, width
, height
));
488 /* grab color and format info from source DIB */
489 if(!_DIBDRVBITMAP_InitFromDibdrvbitmap(dib
, src
, FALSE
))
491 ERR("Failed grabbing source dib format\n");
495 /* sets up new DIB dimensions */
497 dib
->height
= height
;
499 /* calculates new stride basing of new width */
500 dib
->stride
= ((width
* dib
->bitCount
+31) &~31) / 8;
502 dib
->stride
= -dib
->stride
;
503 dib
->topdown
= src
->topdown
;
505 /* allocates bits for newly created DIB */
506 if(!(dib
->bits
= HeapAlloc(GetProcessHeap(), 0, height
*abs(dib
->stride
))))
508 ERR("Failed to allocate bits buffer\n");
511 /* check for bottom-up DIB */
513 dib
->bits
= (BYTE
*)dib
->bits
- (dib
->height
-1) * dib
->stride
;
514 dib
->ownsBits
= TRUE
;
516 MAYBE(TRACE("END\n"));
520 /* Clears a DIBDRVBITMAP structure data
521 WARNING : doesn't free anything */
522 void _DIBDRVBITMAP_Clear(DIBDRVBITMAP
*bmp
)
524 MAYBE(TRACE("bmp=%p\n", bmp
));
529 bmp
->ownsBits
= FALSE
;
530 bmp
->colorTable
= NULL
;
531 bmp
->colorTableSize
= 0;
532 bmp
->colorTableGrabbed
= FALSE
;
534 MAYBE(TRACE("END\n"));
537 /* allocates a new DIBDTVBITMAP */
538 DIBDRVBITMAP
*_DIBDRVBITMAP_New(void)
540 DIBDRVBITMAP
*bmp
= HeapAlloc(GetProcessHeap(), 0, sizeof(DIBDRVBITMAP
));
543 _DIBDRVBITMAP_Clear(bmp
);
547 /* Frees a DIBDRVBITMAP structure data */
548 void _DIBDRVBITMAP_Free(DIBDRVBITMAP
*bmp
)
550 MAYBE(TRACE("bmp=%p\n", bmp
));
554 /* frees bits, if needed */
555 if(bmp
->bits
&& bmp
->ownsBits
)
557 /* on bottom-up dibs, bits doesn't point to starting
558 of buffer.... bad design choice */
560 bmp
->bits
= (BYTE
*)bmp
->bits
+ bmp
->stride
* (bmp
->height
-1);
561 HeapFree(GetProcessHeap(), 0, bmp
->bits
);
563 /* frees color table */
565 HeapFree(GetProcessHeap(), 0, bmp
->colorTable
);
567 HeapFree(GetProcessHeap(), 0, bmp
);
572 /* checks whether the format of 2 DIBs are identical
573 it checks the pixel bit count and the color table size
574 and content, if needed */
575 BOOL
_DIBDRVBITMAP_FormatMatch(const DIBDRVBITMAP
*d1
, const DIBDRVBITMAP
*d2
)
577 /* checks at first the format (bit count and color masks) */
578 if(d1
->format
!= d2
->format
)
581 /* formats matches, now checks color tables if needed */
584 case DIBFMT_DIB32_RGB
:
585 case DIBFMT_DIB32_BITFIELDS
:
587 case DIBFMT_DIB16_RGB
:
588 case DIBFMT_DIB16_BITFIELDS
:
593 /*case DIBFMT_DIB4_RLE :*/
595 /*case DIBFMT_DIB8_RLE :*/
596 if(d1
->colorTableSize
!= d2
->colorTableSize
)
598 return !memcmp(d1
->colorTable
, d2
->colorTable
, d1
->colorTableSize
* sizeof(d1
->colorTable
[0]));
601 ERR("Unexpected depth %d\n", d1
->bitCount
);
606 /* convert a given dib into another format given by 'format' parameter */
607 BOOL
_DIBDRVBITMAP_Convert(DIBDRVBITMAP
*dst
, const DIBDRVBITMAP
*src
, const DIBDRVBITMAP
*format
)
614 MAYBE(TRACE("dst=%p, src=%p, format=%p\n", dst
, src
, format
));
616 /* free, if needed, destination bitmap */
617 _DIBDRVBITMAP_Free(dst
);
619 /* if format and source bitmaps format match,
620 just copy source on destination */
621 if(_DIBDRVBITMAP_FormatMatch(src
, format
))
623 res
= _DIBDRVBITMAP_InitFromDibdrvbitmap(dst
, src
, TRUE
);
624 MAYBE(TRACE("END - Identical formats\n"));
628 /* formats don't match, we create the dest bitmap with same format as format's one
629 but with source's one dimensions */
631 height
= src
->height
;
632 if(!_DIBDRVBITMAP_CreateFromDibdrvbitmap(dst
, format
, width
, height
))
634 ERR("Couldn't create destination bmp\n");
638 /* we now copy/convert from source to dest */
639 if(!(buf
= HeapAlloc(GetProcessHeap(), 0, width
* 4)))
641 ERR("HeapAlloc failed\n");
645 for(iLine
= 0; iLine
< height
; iLine
++)
647 src
->funcs
->GetLine(src
, iLine
, 0, width
, buf
);
648 dst
->funcs
->PutLine(dst
, iLine
, 0, width
, buf
);
650 HeapFree(GetProcessHeap(), 0, buf
);
652 MAYBE(TRACE("END - different formats\n"));
656 /* creates a solid-filled DIB of given color and format
657 DIB format is given by 'format' parameter */
658 BOOL
_DIBDRVBITMAP_CreateSolid(DIBDRVBITMAP
*bmp
, DIBDRVBITMAP
*format
, int width
, int height
, DWORD Color
)
663 MAYBE(TRACE("bmp=%p, format=%p, width=%d, height=%d, Color=%08x\n", bmp
, format
, width
, height
, Color
));
665 /* swaps color bytes....*/
666 Color
= RGB((Color
>> 8) & 0xff, (Color
>> 16) &0xff, Color
&0xff);
668 /* creates the destination bitmap */
669 if(!_DIBDRVBITMAP_CreateFromDibdrvbitmap(bmp
, format
, width
, height
))
671 ERR("Couldn't create destination bmp\n");
675 /* creates a temporary line filled with given color */
676 if(!(buf
= HeapAlloc(GetProcessHeap(), 0, width
* 4)))
678 ERR("HeapAlloc failed\n");
682 for(i
= 0, bufPnt
= buf
; i
< width
; i
++)
685 /* fills the bitmap */
686 for(i
= 0; i
< height
; i
++)
687 bmp
->funcs
->PutLine(bmp
, i
, 0, width
, buf
);
689 /* frees temporaty line */
690 HeapFree(GetProcessHeap(), 0, buf
);
692 MAYBE(TRACE("END\n"));
696 /* expands horizontally a bitmap to reach a minimum size,
697 keeping its width as a multiple of a base width
698 Used to widen brushes in order to optimize blitting */
699 BOOL
_DIBDRVBITMAP_ExpandHoriz(DIBDRVBITMAP
*dib
, int baseWidth
, int minWidth
)
701 BYTE
*srcBuf
, *dstBuf
;
708 MAYBE(TRACE("dib=%p, baseWidth=%d, minWidth=%d\n", dib
, baseWidth
, minWidth
));
710 /* if dst dib already wide enough, just do nothing */
711 if(dib
->width
>= minWidth
)
713 MAYBE(TRACE("END - No need to expand\n"));
717 /* source DIB can't be NULL */
720 ERR("Empty source DIB detected\n");
724 /* round up minWidth to be a multiple of source width */
725 minWidth
+= (baseWidth
- (minWidth
% baseWidth
));
727 /* creates a temporary destination bitmap with required sizes */
728 _DIBDRVBITMAP_Clear(&tmpDib
);
729 if(!_DIBDRVBITMAP_CreateFromDibdrvbitmap(&tmpDib
, dib
, minWidth
, dib
->height
))
731 ERR("Couldn't create the temporary DIB for brush cache\n");
735 /* if format uses almost 1 byte/pixel, fast copy path */
736 if(dib
->bitCount
>= 8)
738 chunkSize
= dib
->width
* dib
->bitCount
/ 8;
739 for(iLine
= 0; iLine
< dib
->height
; iLine
++)
741 srcBuf
= (BYTE
*)dib
->bits
+ iLine
* dib
->stride
;
742 dstBuf
= (BYTE
*)tmpDib
.bits
+ iLine
* tmpDib
.stride
;
743 for(iCol
= 0; iCol
< tmpDib
.width
; iCol
+= dib
->width
)
745 memcpy(dstBuf
, srcBuf
, chunkSize
);
750 /* otherwise slow path -- could be optimized */
753 chunkSize
= dib
->width
* 4;
754 /* allocates a line buffer */
755 if(!(srcBuf
= HeapAlloc(GetProcessHeap(), 0, tmpDib
.width
* 4)))
757 ERR("HeapAlloc failed\n");
761 FIXME("dib:format=%s, funcs=%p, bits=%p, width=%d, height=%d, stride=%d\n",
762 _DIBDRVBITMAP_GetFormatName(dib
), dib
->funcs
, dib
->bits
, dib
->width
, dib
->height
, dib
->stride
);
763 for(iLine
= 0; iLine
< dib
->height
; iLine
++)
765 /* fills the line buffer repeating source's line data */
766 dib
->funcs
->GetLine(dib
, iLine
, 0, dib
->width
, srcBuf
);
767 dstBuf
= srcBuf
+ chunkSize
;
768 for(iCol
= dib
->width
; iCol
< tmpDib
.width
; iCol
+= dib
->width
)
770 memcpy(dstBuf
, srcBuf
, chunkSize
);
773 /* stores the line on destination bmp */
774 tmpDib
.funcs
->PutLine(&tmpDib
, iLine
, 0, tmpDib
.width
, srcBuf
);
776 HeapFree(GetProcessHeap(), 0, srcBuf
);
779 /* swaps temp DIB and source one */
781 ownsBits
= dib
->ownsBits
;
782 dib
->bits
= tmpDib
.bits
;
783 dib
->ownsBits
= tmpDib
.ownsBits
;
785 tmpDib
.ownsBits
= ownsBits
;
787 /* frees the temporary DIB */
788 _DIBDRVBITMAP_Free(&tmpDib
);
790 MAYBE(TRACE("END\n"));