8e6b65319336ba1677770d5178a8151aa3e1e392
[wine/hacks.git] / dlls / winedib.drv / dibdrvbitmap.c
blob8e6b65319336ba1677770d5178a8151aa3e1e392
1 /*
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include "dibdrv.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
28 /* gets human-readable dib format name */
29 const char *_DIBDRVBITMAP_GetFormatName(DIBDRVBITMAP const *bmp)
31 if(!bmp)
33 ERR("Null bitmap\n");
34 return "NULL BITMAP DETECTED";
36 switch(bmp->format)
38 case DIBFMT_DIB1:
39 return "DIBFMT_DIB1";
40 case DIBFMT_DIB4:
41 return "DIBFMT_DIB4";
42 case DIBFMT_DIB4_RLE:
43 return "DIBFMT_DIB4_RLE";
44 case DIBFMT_DIB8:
45 return "DIBFMT_DIB8";
46 case DIBFMT_DIB8_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";
52 case DIBFMT_DIB24:
53 return "DIBFMT_DIB24";
54 case DIBFMT_DIB32_RGB:
55 return "DIBFMT_DIB32_RGB";
56 case DIBFMT_DIB32_BITFIELDS:
57 return "DIBFMT_DIB32_BITFIELDS";
58 case DIBFMT_UNKNOWN:
59 default:
60 return "DIBFMT_UNKNOWN";
64 /* calculates shift and length given a bit mask */
65 static void CalcShiftAndLen(DWORD mask, int *shift, int *len)
67 int s, l;
69 /* FIXME----*/
70 if(mask == 0)
72 FIXME("color mask == 0 -- problem on init_dib\n");
73 *shift = 0;
74 *len = 0;
75 return;
78 /* calculates bit shift
79 (number of 0's on right of bit field */
80 s = 0;
81 while ((mask & 1) == 0)
83 mask >>= 1;
84 s++;
87 /* calculates bitfield length
88 (number of 1's in bit field */
89 l = 0;
90 while ((mask & 1) == 1)
92 mask >>= 1;
93 l++;
95 *shift = s;
96 *len = l;
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 */
115 if(dib->stride > 0)
117 /* top-down dib */
118 dib->bits = bits;
120 else
122 /* bottom-up dib */
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 */
132 if(dib->stride > 0)
134 /* top-down dib */
135 return dib->bits;
137 else
139 /* bottom-up dib */
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 /* initializes dib from a bitmap :
146 dib dib being initialized
147 bi source BITMAPINFOHEADER with required DIB format info
148 bit_fields color masks
149 colorTable color table, if any
150 bits pointer to image data array
151 NOTE : DIBDRVBITMAP doesn't owns bits, but do own color table
153 BOOL _DIBDRVBITMAP_InitFromBMIH(DIBDRVBITMAP *dib, const BITMAPINFOHEADER *bi, const DWORD *bit_fields,
154 const RGBQUAD *colorTable, void *bits)
156 MAYBE(TRACE("dib=%p, bi=%p, bit_fields=%p, colorTable=%p, bits=%p\n", dib, bi, bit_fields, colorTable, bits));
158 /* initializes DIB dimensions and color depth */
159 dib->bitCount = bi->biBitCount;
160 dib->width = bi->biWidth;
161 dib->height = bi->biHeight;
162 dib->stride = ((dib->width * dib->bitCount + 31) >> 3) & ~3;
164 /* initializes image data pointer */
165 dib->bits = bits;
166 dib->ownsBits = FALSE;
168 /* initializes color table */
169 dib->colorTableSize = 0;
170 dib->colorTable = NULL;
171 dib->colorTableGrabbed = FALSE;
173 /* checks whether dib is top-down or bottom-up one */
174 if(dib->height < 0)
176 /* top-down dib */
177 dib->height = -dib->height;
179 else
181 /* bottom-up dib */
182 /* data->bits always points to the top-left corner and the stride is -ve */
183 dib->bits = (BYTE*)dib->bits + (dib->height - 1) * dib->stride;
184 dib->stride = -dib->stride;
187 /* gets and stores bitmap format */
188 switch(dib->bitCount)
190 case 24:
191 dib->format = DIBFMT_DIB24;
192 dib->funcs = &DIBDRV_funcs_DIB24;
193 break;
195 case 32:
197 if(bi->biCompression == BI_RGB)
199 dib->format = DIBFMT_DIB32_RGB;
200 dib->funcs = &DIBDRV_funcs_DIB32_RGB;
202 else
204 InitBitFields(dib, bit_fields);
205 dib->format = DIBFMT_DIB32_BITFIELDS;
206 dib->funcs = &DIBDRV_funcs_DIB32_BITFIELDS;
208 break;
210 case 16:
211 if(bi->biCompression == BI_RGB)
213 dib->format = DIBFMT_DIB16_RGB;
214 dib->funcs = &DIBDRV_funcs_DIB16_RGB;
216 else
218 InitBitFields(dib, bit_fields);
219 dib->format = DIBFMT_DIB16_BITFIELDS;
220 dib->funcs = &DIBDRV_funcs_DIB16_BITFIELDS;
222 break;
224 case 8:
225 dib->format = DIBFMT_DIB8;
226 dib->funcs = &DIBDRV_funcs_DIB8;
227 dib->colorTableSize = 256;
228 if(bi->biClrUsed) dib->colorTableSize = bi->biClrUsed;
229 break;
231 case 4:
232 dib->format = DIBFMT_DIB4;
233 dib->funcs = &DIBDRV_funcs_DIB4;
234 dib->colorTableSize = 16;
235 if(bi->biClrUsed) dib->colorTableSize = bi->biClrUsed;
236 break;
238 case 1:
239 dib->format = DIBFMT_DIB1;
240 dib->funcs = &DIBDRV_funcs_DIB1;
241 dib->colorTableSize = 2;
242 if(bi->biClrUsed) dib->colorTableSize = bi->biClrUsed;
243 break;
245 default:
246 dib->format = DIBFMT_UNKNOWN;
247 dib->funcs = NULL;
248 FIXME("bpp %d not supported\n", dib->bitCount);
249 return FALSE;
251 MAYBE(TRACE("DIB FORMAT : %s\n", _DIBDRVBITMAP_GetFormatName(dib)));
253 /* allocates color table and copy it from source, *if* source is
254 not null */
255 if(dib->colorTableSize && colorTable)
257 if(!(dib->colorTable = HeapAlloc(GetProcessHeap(), 0,
258 dib->colorTableSize * sizeof(dib->colorTable[0]))
261 ERR("HeapAlloc failed\n");
262 return FALSE;
264 memcpy(dib->colorTable, colorTable,
265 dib->colorTableSize * sizeof(dib->colorTable[0]));
266 dib->colorTableGrabbed = TRUE;
268 else if(!dib->colorTableSize)
269 /* no color table on more than 8 bits/pixel */
270 dib->colorTableGrabbed = TRUE;
272 MAYBE(TRACE("END\n"));
273 return TRUE;
276 BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, const BITMAPINFO *bmi)
278 static const DWORD bit_fields_DIB32_RGB[3] = {0xff0000, 0x00ff00, 0x0000ff};
279 static const DWORD bit_fields_DIB16_RGB[3] = {0x7c00, 0x03e0, 0x001f};
280 BITMAPINFOHEADER *bi = (BITMAPINFOHEADER *)bmi;
281 const DWORD *masks = NULL;
282 RGBQUAD *colorTable = NULL;
283 BYTE *ptr = (BYTE*)bmi + bi->biSize;
284 int num_colors = bi->biClrUsed;
285 BOOL res;
287 MAYBE(TRACE("dib=%p, bmi=%p\n", dib, bmi));
289 if(bi->biCompression == BI_BITFIELDS)
291 masks = (DWORD *)ptr;
292 ptr += 3 * sizeof(DWORD);
294 else if(bi->biBitCount == 32)
295 masks = bit_fields_DIB32_RGB;
296 else if(bi->biBitCount == 16)
297 masks = bit_fields_DIB16_RGB;
299 if(!num_colors && bi->biBitCount <= 8)
300 num_colors = 1 << bi->biBitCount;
301 if(num_colors)
302 colorTable = (RGBQUAD*)ptr;
303 ptr += num_colors * sizeof(*colorTable);
305 res = _DIBDRVBITMAP_InitFromBMIH(dib, bi, masks, colorTable, ptr);
306 MAYBE(TRACE("END\n"));
307 return res;
310 /* initializes a DIBRDVBITMAP copying it from a source one
311 Parameters :
312 dib destination DIBDRVBITMAP
313 src source DIBDRVBITMAP
314 copy TRUE->copy source pixel array FALSE->link to source pixel array
316 BOOL _DIBDRVBITMAP_InitFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *src, BOOL copy)
318 MAYBE(TRACE("dib=%p, src=%p, copy=%d\n", dib, src, copy));
320 dib->format = src->format;
321 dib->width = src->width;
322 dib->height = src->height;
323 dib->stride = src->stride;
324 dib->bitCount = src->bitCount;
326 dib->redMask = src->redMask;
327 dib->greenMask = src->greenMask;
328 dib->blueMask = src->blueMask;
329 dib->redShift = src->redShift;
330 dib->greenShift = src->greenShift;
331 dib->blueShift = src->blueShift;
332 dib->redLen = src->redLen;
333 dib->greenLen = src->greenLen;
334 dib->blueLen = src->blueLen;
336 dib->funcs = src->funcs;
338 if(copy)
340 int size = dib->height*abs(dib->stride);
341 if(!(dib->bits = HeapAlloc(GetProcessHeap(), 0, size)))
343 ERR("Failed to allocate bits buffer\n");
344 return FALSE;
346 dib->ownsBits = TRUE;
348 /* check for bottom-up DIB */
349 if(dib->stride < 0)
351 /* copy the bitmap array */
352 memcpy(dib->bits, (BYTE *)src->bits + (src->height - 1) * src->stride, size);
354 dib->bits = (BYTE *)dib->bits - (dib->height-1) * dib->stride;
356 else
358 /* copy the bitmap array */
359 memcpy(dib->bits, src->bits, size);
362 else
364 dib->bits = src->bits;
365 dib->ownsBits = FALSE;
368 if(src->colorTable)
370 dib->colorTable = HeapAlloc(GetProcessHeap(), 0, src->colorTableSize * sizeof(src->colorTable[0]));
371 memcpy(dib->colorTable, src->colorTable, src->colorTableSize * sizeof(src->colorTable[0]));
373 else
374 dib->colorTable = NULL;
375 dib->colorTableSize = src->colorTableSize;
376 dib->colorTableGrabbed = TRUE;
377 MAYBE(TRACE("END\n"));
378 return TRUE;
381 /* initializes a DIBRDVBITMAP from a DIB HBITMAP
382 Parameters :
383 bmp destination DIBDRVBITMAP
384 hbmp source HBITMAP
385 copyPixels TRUE->copy source pixel array FALSE->link to source pixel array */
386 BOOL _DIBDRVBITMAP_InitFromHBITMAP(DIBDRVBITMAP *bmp, const HBITMAP hbmp, BOOL copyPixels)
388 BITMAPINFO *destInfo;
389 DIBSECTION ds;
390 int size;
392 MAYBE(TRACE("bmp=%p, hbmp=%p, copyPixels = %s\n", bmp, hbmp, copyPixels ? "TRUE" : "FALSE"));
394 /* be sure bitmap is empty */
395 _DIBDRVBITMAP_Clear(bmp);
397 /* gets source bitmap data */
398 if(!(size = GetObjectW(hbmp, sizeof(DIBSECTION), &ds)))
400 ERR("Failed getting bitmap object\n");
401 return FALSE;
403 if(size != sizeof(DIBSECTION))
405 ERR("Bitmap is not a DIB section\n");
406 return FALSE;
409 destInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
410 if(!destInfo)
412 ERR("HeapAlloc failed\n");
413 return FALSE;
416 memcpy(destInfo, &ds.dsBmih, sizeof(BITMAPINFOHEADER));
417 if(ds.dsBmih.biCompression == BI_BITFIELDS)
418 memcpy((BITMAPINFOHEADER *)destInfo + 1, ds.dsBitfields, 3 * sizeof(RGBQUAD));
419 else if(ds.dsBmih.biBitCount <= 8)
421 FIXME("Can't grab color table here.... syslvel lock\n");
422 return FALSE;
423 #if 0
424 HDC refDC = CreateCompatibleDC(0);
425 if(!refDC)
427 ERR("CreateCompatibleDC() failed\n");
428 return FALSE;
430 if(!GetDIBits(refDC, hbmp, 0, 1, NULL, destInfo, DIB_RGB_COLORS))
432 DeleteDC(refDC);
433 HeapFree(GetProcessHeap(), 0, destInfo);
434 ERR("GetDIBits failed\n");
435 return FALSE;
437 DeleteDC(refDC);
438 #endif
440 if(!_DIBDRVBITMAP_InitFromBitmapinfo(bmp, destInfo))
442 HeapFree(GetProcessHeap(), 0, destInfo);
443 ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
444 return FALSE;
446 HeapFree(GetProcessHeap(), 0, destInfo);
447 if(copyPixels)
449 size = abs(bmp->stride) * bmp->height;
450 if(!(bmp->bits = HeapAlloc(GetProcessHeap(), 0, size)))
452 ERR("HeapAlloc failed\n");
453 _DIBDRVBITMAP_Free(bmp);
454 return FALSE;
456 memcpy(bmp->bits, ds.dsBm.bmBits, size);
457 bmp->ownsBits = TRUE;
459 else
460 bmp->bits = ds.dsBm.bmBits;
461 if(bmp->stride < 0)
462 bmp->bits = (BYTE*)bmp->bits - (bmp->height - 1) * bmp->stride;
464 return TRUE;
468 /* creates a DIBRDVBITMAP copying format info from a source one
469 Parameters :
470 dib destination DIBDRVBITMAP
471 src source DIBDRVBITMAP
472 widht, height sizes of newly created bitmap
474 BOOL _DIBDRVBITMAP_CreateFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *src, int width, int height)
476 MAYBE(TRACE("dib=%p, src=%p, width=%d, height=%d\n", dib, src, width, height));
478 /* grab color and format info from source DIB */
479 if(!_DIBDRVBITMAP_InitFromDibdrvbitmap(dib, src, FALSE))
481 ERR("Failed grabbing source dib format\n");
482 return FALSE;
485 /* sets up new DIB dimensions */
486 dib->width = width;
487 dib->height = height;
489 /* calculates new stride basing of new width */
490 dib->stride = ((width * dib->bitCount +31) &~31) / 8;
491 if(src->stride < 0)
492 dib->stride = -dib->stride;
494 /* allocates bits for newly created DIB */
495 if(!(dib->bits = HeapAlloc(GetProcessHeap(), 0, height*abs(dib->stride))))
497 ERR("Failed to allocate bits buffer\n");
498 return FALSE;
500 /* check for bottom-up DIB */
501 if(dib->stride < 0)
502 dib->bits = (BYTE *)dib->bits - (dib->height-1) * dib->stride;
503 dib->ownsBits = TRUE;
505 MAYBE(TRACE("END\n"));
506 return TRUE;
509 /* Clears a DIBDRVBITMAP structure data
510 WARNING : doesn't free anything */
511 void _DIBDRVBITMAP_Clear(DIBDRVBITMAP *bmp)
513 MAYBE(TRACE("bmp=%p\n", bmp));
515 bmp->bits = NULL;
516 bmp->ownsBits = FALSE;
517 bmp->colorTable = NULL;
518 bmp->colorTableSize = 0;
519 bmp->colorTableGrabbed = FALSE;
521 MAYBE(TRACE("END\n"));
524 /* Frees a DIBDRVBITMAP structure data */
525 void _DIBDRVBITMAP_Free(DIBDRVBITMAP *bmp)
527 MAYBE(TRACE("bmp=%p\n", bmp));
529 /* frees bits, if needed */
530 if(bmp->bits && bmp->ownsBits)
532 /* on bottom-up dibs, bits doesn't point to starting
533 of buffer.... bad design choice */
534 if(bmp->stride < 0)
535 bmp->bits = (BYTE *)bmp->bits + bmp->stride * (bmp->height -1);
536 HeapFree(GetProcessHeap(), 0, bmp->bits);
538 bmp->ownsBits = FALSE;
539 bmp->bits = NULL;
541 /* frees color table */
542 if(bmp->colorTable)
543 HeapFree(GetProcessHeap(), 0, bmp->colorTable);
544 bmp->colorTable = NULL;
545 bmp->colorTableSize = 0;
546 bmp->colorTableGrabbed = FALSE;
548 MAYBE(TRACE("END\n"));
552 /* checks whether the format of 2 DIBs are identical
553 it checks the pixel bit count and the color table size
554 and content, if needed */
555 BOOL _DIBDRVBITMAP_FormatMatch(const DIBDRVBITMAP *d1, const DIBDRVBITMAP *d2)
557 /* checks at first the format (bit count and color masks) */
558 if(d1->format != d2->format)
559 return FALSE;
561 /* formats matches, now checks color tables if needed */
562 switch(d1->format)
564 case DIBFMT_DIB32_RGB :
565 case DIBFMT_DIB32_BITFIELDS :
566 case DIBFMT_DIB24 :
567 case DIBFMT_DIB16_RGB :
568 case DIBFMT_DIB16_BITFIELDS :
569 return TRUE;
571 case DIBFMT_DIB1 :
572 case DIBFMT_DIB4 :
573 /*case DIBFMT_DIB4_RLE :*/
574 case DIBFMT_DIB8 :
575 /*case DIBFMT_DIB8_RLE :*/
576 if(d1->colorTableSize != d2->colorTableSize)
577 return FALSE;
578 return !memcmp(d1->colorTable, d2->colorTable, d1->colorTableSize * sizeof(d1->colorTable[0]));
580 default:
581 ERR("Unexpected depth %d\n", d1->bitCount);
582 return FALSE;
586 /* convert a given dib into another format given by 'format' parameter */
587 BOOL _DIBDRVBITMAP_Convert(DIBDRVBITMAP *dst, const DIBDRVBITMAP *src, const DIBDRVBITMAP *format)
589 int width, height;
590 int iLine;
591 void *buf;
592 BOOL res;
594 MAYBE(TRACE("dst=%p, src=%p, format=%p\n", dst, src, format));
596 /* free, if needed, destination bitmap */
597 _DIBDRVBITMAP_Free(dst);
599 /* if format and source bitmaps format match,
600 just copy source on destination */
601 if(_DIBDRVBITMAP_FormatMatch(src, format))
603 res = _DIBDRVBITMAP_InitFromDibdrvbitmap(dst, src, TRUE);
604 MAYBE(TRACE("END - Identical formats\n"));
605 return res;
608 /* formats don't match, we create the dest bitmap with same format as format's one
609 but with source's one dimensions */
610 width = src->width;
611 height = src->height;
612 if(!_DIBDRVBITMAP_CreateFromDibdrvbitmap(dst, format, width, height))
614 ERR("Couldn't create destination bmp\n");
615 return FALSE;
618 /* we now copy/convert from source to dest */
619 if(!(buf = HeapAlloc(GetProcessHeap(), 0, width * 4)))
621 ERR("HeapAlloc failed\n");
622 return FALSE;
625 for(iLine = 0; iLine < height; iLine++)
627 src->funcs->GetLine(src, iLine, 0, width, buf);
628 dst->funcs->PutLine(dst, iLine, 0, width, buf);
630 HeapFree(GetProcessHeap(), 0, buf);
632 MAYBE(TRACE("END - different formats\n"));
633 return TRUE;
636 /* creates a solid-filled DIB of given color and format
637 DIB format is given by 'format' parameter */
638 BOOL _DIBDRVBITMAP_CreateSolid(DIBDRVBITMAP *bmp, DIBDRVBITMAP *format, int width, int height, DWORD Color)
640 DWORD *buf, *bufPnt;
641 int i;
643 MAYBE(TRACE("bmp=%p, format=%p, width=%d, height=%d, Color=%08x\n", bmp, format, width, height, Color));
645 /* swaps color bytes....*/
646 Color = RGB((Color >> 8) & 0xff, (Color >> 16) &0xff, Color &0xff);
648 /* creates the destination bitmap */
649 if(!_DIBDRVBITMAP_CreateFromDibdrvbitmap(bmp, format, width, height))
651 ERR("Couldn't create destination bmp\n");
652 return FALSE;
655 /* creates a temporary line filled with given color */
656 if(!(buf = HeapAlloc(GetProcessHeap(), 0, width * 4)))
658 ERR("HeapAlloc failed\n");
659 return FALSE;
662 for(i = 0, bufPnt = buf; i < width; i++)
663 *bufPnt++ = Color;
665 /* fills the bitmap */
666 for(i = 0; i < height; i++)
667 bmp->funcs->PutLine(bmp, i, 0, width, buf);
669 /* frees temporaty line */
670 HeapFree(GetProcessHeap(), 0, buf);
672 MAYBE(TRACE("END\n"));
673 return TRUE;
676 /* expands horizontally a bitmap to reach a minimum size,
677 keeping its width as a multiple of a base width
678 Used to widen brushes in order to optimize blitting */
679 BOOL _DIBDRVBITMAP_ExpandHoriz(DIBDRVBITMAP *dib, int baseWidth, int minWidth)
681 BYTE *srcBuf, *dstBuf;
682 int chunkSize;
683 int iLine, iCol;
684 DIBDRVBITMAP tmpDib;
685 void *bits;
686 BOOL ownsBits;
688 MAYBE(TRACE("dib=%p, baseWidth=%d, minWidth=%d\n", dib, baseWidth, minWidth));
690 /* if dst dib already wide enough, just do nothing */
691 if(dib->width >= minWidth)
693 MAYBE(TRACE("END - No need to expand\n"));
694 return TRUE;
697 /* source DIB can't be NULL */
698 if(!dib->bits)
700 ERR("Empty source DIB detected\n");
701 return FALSE;
704 /* round up minWidth to be a multiple of source width */
705 minWidth += (baseWidth - (minWidth % baseWidth));
707 /* creates a temporary destination bitmap with required sizes */
708 _DIBDRVBITMAP_Clear(&tmpDib);
709 if(!_DIBDRVBITMAP_CreateFromDibdrvbitmap(&tmpDib, dib, minWidth, dib->height))
711 ERR("Couldn't create the temporary DIB for brush cache\n");
712 return FALSE;
715 /* if format uses almost 1 byte/pixel, fast copy path */
716 if(dib->bitCount >= 8)
718 chunkSize = dib->width * dib->bitCount / 8;
719 for(iLine = 0; iLine < dib->height; iLine++)
721 srcBuf = (BYTE *)dib->bits + iLine * dib->stride;
722 dstBuf = (BYTE *)tmpDib.bits + iLine * tmpDib.stride;
723 for(iCol = 0; iCol < tmpDib.width; iCol += dib->width)
725 memcpy(dstBuf, srcBuf, chunkSize);
726 dstBuf += chunkSize;
730 /* otherwise slow path -- could be optimized */
731 else
733 chunkSize = dib->width * 4;
734 /* allocates a line buffer */
735 if(!(srcBuf = HeapAlloc(GetProcessHeap(), 0, tmpDib.width * 4)))
737 ERR("HeapAlloc failed\n");
738 return FALSE;
741 FIXME("dib:format=%s, funcs=%p, bits=%p, width=%d, height=%d, stride=%d\n",
742 _DIBDRVBITMAP_GetFormatName(dib), dib->funcs, dib->bits, dib->width, dib->height, dib->stride);
743 for(iLine = 0; iLine < dib->height; iLine++)
745 /* fills the line buffer repeating source's line data */
746 dib->funcs->GetLine(dib, iLine, 0, dib->width, srcBuf);
747 dstBuf = srcBuf + chunkSize;
748 for(iCol = dib->width; iCol < tmpDib.width; iCol += dib->width)
750 memcpy(dstBuf, srcBuf, chunkSize);
751 dstBuf += chunkSize;
753 /* stores the line on destination bmp */
754 tmpDib.funcs->PutLine(&tmpDib, iLine, 0, tmpDib.width, srcBuf);
756 HeapFree(GetProcessHeap(), 0, srcBuf);
759 /* swaps temp DIB and source one */
760 bits = dib->bits;
761 ownsBits = dib->ownsBits;
762 dib->bits = tmpDib.bits;
763 dib->ownsBits = tmpDib.ownsBits;
764 tmpDib.bits = bits;
765 tmpDib.ownsBits = ownsBits;
767 /* frees the temporary DIB */
768 _DIBDRVBITMAP_Free(&tmpDib);
770 MAYBE(TRACE("END\n"));
771 return TRUE;