xref: /reactos/win32ss/gdi/dib/dib8bpp.c (revision 463784c5)
1 /*
2  * PROJECT:         Win32 subsystem
3  * LICENSE:         See COPYING in the top level directory
4  * FILE:            win32ss/gdi/dib/dib8bpp.c
5  * PURPOSE:         Device Independant Bitmap functions, 8bpp
6  * PROGRAMMERS:     Jason Filby
7  *                  Thomas Bluemel
8  *                  Gregor Anich
9  *                  Doug Lyons
10  */
11 
12 #include <win32k.h>
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 #define DEC_OR_INC(var, decTrue, amount) \
18     ((var) = (decTrue) ? ((var) - (amount)) : ((var) + (amount)))
19 
20 VOID
21 DIB_8BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
22 {
23   PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + x;
24 
25   *byteaddr = (BYTE)c;
26 }
27 
28 ULONG
29 DIB_8BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
30 {
31   PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + x;
32 
33   return (ULONG)(*byteaddr);
34 }
35 
36 VOID
37 DIB_8BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
38 {
39   memset((PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta + x1, (BYTE) c, x2 - x1);
40 }
41 
42 VOID
43 DIB_8BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
44 {
45   PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y1 * SurfObj->lDelta;
46   PBYTE addr = byteaddr + x;
47   LONG lDelta = SurfObj->lDelta;
48 
49   byteaddr = addr;
50   while(y1++ < y2)
51   {
52     *addr = (BYTE)c;
53 
54     addr += lDelta;
55   }
56 }
57 
58 BOOLEAN
59 DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo)
60 {
61   LONG     i, j, sx, sy, xColor, f1;
62   PBYTE    SourceBits, DestBits, SourceLine, DestLine;
63   PBYTE    SourceBits_4BPP, SourceLine_4BPP;
64   BOOLEAN  bTopToBottom, bLeftToRight;
65 
66   DPRINT("DIB_8BPP_BitBltSrcCopy: SrcSurf cx/cy (%d/%d), DestSuft cx/cy (%d/%d) dstRect: (%d,%d)-(%d,%d)\n",
67          BltInfo->SourceSurface->sizlBitmap.cx, BltInfo->SourceSurface->sizlBitmap.cy,
68          BltInfo->DestSurface->sizlBitmap.cx, BltInfo->DestSurface->sizlBitmap.cy,
69          BltInfo->DestRect.left, BltInfo->DestRect.top, BltInfo->DestRect.right, BltInfo->DestRect.bottom);
70 
71   /* Get back left to right flip here */
72   bLeftToRight = (BltInfo->DestRect.left > BltInfo->DestRect.right);
73 
74   /* Check for top to bottom flip needed. */
75   bTopToBottom = BltInfo->DestRect.top > BltInfo->DestRect.bottom;
76 
77   DPRINT("bTopToBottom is '%d' and bLeftToRight is '%d'.\n", bTopToBottom, bLeftToRight);
78 
79   /* Make WellOrdered by making top < bottom and left < right */
80   RECTL_vMakeWellOrdered(&BltInfo->DestRect);
81 
82   DPRINT("BPP is '%d' & BltInfo->SourcePoint.x is '%d' & BltInfo->SourcePoint.y is '%d'.\n",
83          BltInfo->SourceSurface->iBitmapFormat, BltInfo->SourcePoint.x, BltInfo->SourcePoint.y);
84 
85   DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left;
86 
87   switch(BltInfo->SourceSurface->iBitmapFormat)
88   {
89     case BMF_1BPP:
90       DPRINT("1BPP Case Selected with DestRect Width of '%d'.\n",
91              BltInfo->DestRect.right - BltInfo->DestRect.left);
92 
93       sx = BltInfo->SourcePoint.x;
94 
95       /* This sets sy to the top line */
96       sy = BltInfo->SourcePoint.y;
97 
98       if (bTopToBottom)
99       {
100         /* This sets sy to the bottom line */
101         sy += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
102       }
103 
104       for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
105       {
106         sx = BltInfo->SourcePoint.x;
107 
108         if (bLeftToRight)
109         {
110           /* This sets the sx to the rightmost pixel */
111           sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
112         }
113 
114         for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
115         {
116           if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
117           {
118             DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
119           }
120           else
121           {
122             DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
123           }
124           DEC_OR_INC(sx, bLeftToRight, 1);
125         }
126         DEC_OR_INC(sy, bTopToBottom, 1);
127       }
128       break;
129 
130     case BMF_4BPP:
131       DPRINT("4BPP Case Selected with DestRect Width of '%d'.\n",
132              BltInfo->DestRect.right - BltInfo->DestRect.left);
133 
134       /* This sets SourceBits_4BPP to the top line */
135       SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + (BltInfo->SourcePoint.x >> 1);
136 
137       if (bTopToBottom)
138       {
139         /* This sets SourceBits_4BPP to the bottom line */
140         SourceBits_4BPP += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;
141       }
142 
143       for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
144       {
145         SourceLine_4BPP = SourceBits_4BPP;
146         sx = BltInfo->SourcePoint.x;
147 
148         if (bLeftToRight)
149         {
150           /* This sets sx to the rightmost pixel */
151           sx += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
152         }
153 
154         f1 = sx & 1;
155 
156         for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
157         {
158           xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
159               (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
160           DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
161           if(f1 == 1)
162           {
163             DEC_OR_INC(SourceLine_4BPP, bLeftToRight, 1);
164             f1 = 0;
165           }
166           else
167           {
168             f1 = 1;
169           }
170 
171           DEC_OR_INC(sx, bLeftToRight, 1);
172         }
173         DEC_OR_INC(SourceBits_4BPP, bTopToBottom, BltInfo->SourceSurface->lDelta);
174       }
175       break;
176 
177     case BMF_8BPP:
178       DPRINT("8BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
179               BltInfo->DestRect.left, BltInfo->DestRect.top,
180               BltInfo->DestRect.right, BltInfo->DestRect.bottom,
181               BltInfo->DestRect.right - BltInfo->DestRect.left);
182 
183       if ((BltInfo->XlateSourceToDest == NULL ||
184         (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL) != 0) &&
185         (!bTopToBottom && !bLeftToRight))
186       {
187         if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
188         {
189           DPRINT("BltInfo->DestRect.top < BltInfo->SourcePoint.y.\n");
190           SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
191           for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
192           {
193             RtlMoveMemory(DestBits, SourceBits, BltInfo->DestRect.right - BltInfo->DestRect.left);
194             SourceBits += BltInfo->SourceSurface->lDelta;
195             DestBits += BltInfo->DestSurface->lDelta;
196           }
197         }
198         else
199         {
200           DPRINT("BltInfo->DestRect.top >= BltInfo->SourcePoint.y.\n");
201           SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
202           DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left;
203           for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
204           {
205             RtlMoveMemory(DestBits, SourceBits, BltInfo->DestRect.right - BltInfo->DestRect.left);
206             SourceBits -= BltInfo->SourceSurface->lDelta;
207             DestBits -= BltInfo->DestSurface->lDelta;
208           }
209         }
210       }
211       else
212       {
213         DPRINT("XO_TRIVIAL is NOT TRUE or we have flips.\n");
214 
215         if (!bTopToBottom && !bLeftToRight)
216       /* **Note: Indent is purposefully less than desired to keep reviewable differences to a minimum for PR** */
217         {
218         if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
219         {
220           DPRINT("Dest.top < SourcePoint.y.\n");
221           SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
222           DestLine = DestBits;
223           for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
224           {
225             SourceBits = SourceLine;
226             DestBits = DestLine;
227             for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
228             {
229               *DestBits++ = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits++);
230             }
231             SourceLine += BltInfo->SourceSurface->lDelta;
232             DestLine += BltInfo->DestSurface->lDelta;
233           }
234         }
235         else
236         {
237           DPRINT("Dest.top >= SourcePoint.y.\n");
238           SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
239           DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left;
240           for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
241           {
242             SourceBits = SourceLine;
243             DestBits = DestLine;
244             for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
245             {
246               *DestBits++ = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits++);
247             }
248             SourceLine -= BltInfo->SourceSurface->lDelta;
249             DestLine -= BltInfo->DestSurface->lDelta;
250           }
251         }
252       }
253       else
254       {
255           /* Buffering for source and destination flip overlaps. Fixes KHMZ MirrorTest CORE-16642 */
256           BOOL OneDone = FALSE;
257 
258           if (bLeftToRight)
259           {
260             DPRINT("Flip is bLeftToRight.\n");
261 
262             /* Allocate enough pixels for a row in BYTE's */
263             BYTE *store = ExAllocatePoolWithTag(NonPagedPool,
264               BltInfo->DestRect.right - BltInfo->DestRect.left + 1, TAG_DIB);
265             if (store == NULL)
266             {
267               DPRINT1("Storage Allocation Failed.\n");
268               return FALSE;
269             }
270             WORD  Index;
271 
272             /* This sets SourceLine to the top line */
273             SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
274               (BltInfo->SourcePoint.y *
275               BltInfo->SourceSurface->lDelta) +
276               BltInfo->SourcePoint.x;
277 
278             /* This set the DestLine to the top line */
279             DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
280               (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) +
281               BltInfo->DestRect.left;
282 
283             for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
284             {
285               SourceBits = SourceLine;
286               DestBits = DestLine;
287 
288               /* This sets SourceBits to the rightmost pixel */
289               SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
290 
291               Index = 0;
292 
293               for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
294               {
295                 store[Index] = (BYTE)XLATEOBJ_iXlate(
296                   BltInfo->XlateSourceToDest,
297                   *SourceBits);
298                 SourceBits--;
299                 Index++;
300               }
301 
302               Index = 0;
303 
304               for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
305               {
306                 *DestBits = store[Index];
307                 DestBits++;
308                 Index++;
309               }
310 
311               SourceLine += BltInfo->SourceSurface->lDelta;
312               DestLine += BltInfo->DestSurface->lDelta;
313             }
314             ExFreePoolWithTag(store, TAG_DIB);
315             OneDone = TRUE;
316           }
317 
318           if (bTopToBottom)
319           {
320             DPRINT("Flip is bTopToBottom.\n");
321 
322             DWORD  Index;
323 
324             /* Allocate enough pixels for a column in BYTE's */
325             BYTE *store = ExAllocatePoolWithTag(NonPagedPool,
326               BltInfo->DestRect.bottom - BltInfo->DestRect.top + 1, TAG_DIB);
327             if (store == NULL)
328             {
329               DPRINT1("Storage Allocation Failed.\n");
330               return FALSE;
331             }
332 
333             /* The OneDone flag indicates that we are flipping for bTopToBottom and bLeftToRight
334              * and have already completed the bLeftToRight. So we will lose our first flip output
335              * unless we work with its output which is at the destination site. So in this case
336              * our new Source becomes the previous outputs Destination. */
337 
338             if (OneDone)
339             {
340               /* This sets SourceLine to the bottom line of our previous destination */
341               SourceLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
342                 (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + BltInfo->DestRect.left  +
343                 (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->DestSurface->lDelta;
344             }
345             else
346             {
347               /* This sets SourceLine to the bottom line */
348               SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
349                 ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1)
350                 * BltInfo->SourceSurface->lDelta) +
351                 BltInfo->SourcePoint.x;
352             }
353 
354             /* This set the DestLine to the top line */
355             DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
356               (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) +
357               BltInfo->DestRect.left;
358 
359             /* Read columns */
360             for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
361             {
362 
363               DestBits = DestLine;
364               SourceBits = SourceLine;
365 
366               Index = 0;
367 
368               /* Read up the column and store the pixels */
369               for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
370               {
371                 store[Index] = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *SourceBits);
372                 /* Go up a line */
373                 SourceBits -= BltInfo->SourceSurface->lDelta;
374                 Index++;
375               }
376 
377               Index = 0;
378 
379               /* Get the stored pixel and copy then down the column */
380               for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
381               {
382                 *DestBits = store[Index];
383                 /* Go down a line */
384                 DestBits += BltInfo->SourceSurface->lDelta;
385                 Index++;
386               }
387               /* Index to next column */
388               SourceLine += 1;
389               DestLine += 1;
390             }
391             ExFreePoolWithTag(store, TAG_DIB);
392           }
393 
394         }
395       }
396       break;
397 
398     case BMF_16BPP:
399       DPRINT("16BPP Case Selected with DestRect Width of '%d'.\n",
400              BltInfo->DestRect.right - BltInfo->DestRect.left);
401 
402       DPRINT("BMF_16BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
403              BltInfo->DestRect.left, BltInfo->DestRect.top,
404              BltInfo->DestRect.right, BltInfo->DestRect.bottom,
405              BltInfo->DestRect.right - BltInfo->DestRect.left);
406 
407       SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
408 
409       if (bTopToBottom)
410       {
411         /* This sets SourceLine to the bottom line */
412         SourceLine += (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta;;
413       }
414       DestLine = DestBits;
415 
416       for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
417       {
418         SourceBits = SourceLine;
419 
420         if (bLeftToRight)
421         {
422           /* This sets SourceBits to the rightmost pixel */
423           SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 2;
424         }
425         DestBits = DestLine;
426 
427         for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
428         {
429           xColor = *((PWORD) SourceBits);
430           *DestBits = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
431 
432           DEC_OR_INC(SourceBits, bLeftToRight, 2);
433           DestBits += 1;
434         }
435         DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
436         DestLine += BltInfo->DestSurface->lDelta;
437       }
438       break;
439 
440     case BMF_24BPP:
441       DPRINT("24BPP-dstRect: (%d,%d)-(%d,%d) and Width of '%d'.\n",
442              BltInfo->DestRect.left, BltInfo->DestRect.top,
443              BltInfo->DestRect.right, BltInfo->DestRect.bottom,
444              BltInfo->DestRect.right - BltInfo->DestRect.left);
445 
446       SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 3 * BltInfo->SourcePoint.x;
447       DestLine = DestBits;
448 
449       if (bTopToBottom)
450       {
451         /* This sets SourceLine to the bottom line */
452         SourceLine += BltInfo->SourceSurface->lDelta * (BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1);
453       }
454 
455       for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
456       {
457         SourceBits = SourceLine;
458         DestBits = DestLine;
459 
460         if (bLeftToRight)
461         {
462           /* This sets the SourceBits to the rightmost pixel */
463           SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 3;
464         }
465 
466         for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
467         {
468           xColor = (*(SourceBits + 2) << 0x10) +
469              (*(SourceBits + 1) << 0x08) +
470              (*(SourceBits));
471           *DestBits = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
472           DEC_OR_INC(SourceBits, bLeftToRight, 3);
473           DestBits += 1;
474         }
475         DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
476         DestLine += BltInfo->DestSurface->lDelta;
477       }
478       break;
479 
480     case BMF_32BPP:
481       DPRINT("32BPP Case Selected with DestRect Width of '%d'.\n",
482              BltInfo->DestRect.right - BltInfo->DestRect.left);
483 
484       SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
485 
486       if (bTopToBottom)
487       {
488         /* This sets SourceLine to the bottom line */
489         SourceLine += BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1;
490       }
491       DestLine = DestBits;
492 
493       for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
494       {
495         SourceBits = SourceLine;
496         DestBits = DestLine;
497 
498         if (bLeftToRight)
499         {
500           /* This sets SourceBits to the rightmost pixel */
501           SourceBits += (BltInfo->DestRect.right - BltInfo->DestRect.left - 1) * 4;
502         }
503 
504         for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
505         {
506           xColor = *((PDWORD) SourceBits);
507           *DestBits = (BYTE)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
508 
509           DEC_OR_INC(SourceBits, bLeftToRight, 4);
510           DestBits += 1;
511         }
512         DEC_OR_INC(SourceLine, bTopToBottom, BltInfo->SourceSurface->lDelta);
513         DestLine += BltInfo->DestSurface->lDelta;
514       }
515       break;
516 
517     default:
518       DPRINT1("DIB_8BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
519       return FALSE;
520   }
521 
522   return TRUE;
523 }
524 
525 /* BitBlt Optimize */
526 BOOLEAN
527 DIB_8BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
528 {
529   LONG DestY;
530 
531   /* Make WellOrdered by making top < bottom and left < right */
532   RECTL_vMakeWellOrdered(DestRect);
533 
534   for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
535   {
536     DIB_8BPP_HLine(DestSurface, DestRect->left, DestRect->right, DestY, color);
537   }
538   return TRUE;
539 }
540 
541 
542 BOOLEAN
543 DIB_8BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
544                         RECTL*  DestRect,  RECTL *SourceRect,
545                         XLATEOBJ *ColorTranslation, ULONG iTransColor)
546 {
547   LONG RoundedRight, X, Y, SourceX = 0, SourceY = 0;
548   ULONG *DestBits, Source, Dest;
549 
550   LONG DstHeight;
551   LONG DstWidth;
552   LONG SrcHeight;
553   LONG SrcWidth;
554 
555   DstHeight = DestRect->bottom - DestRect->top;
556   DstWidth = DestRect->right - DestRect->left;
557   SrcHeight = SourceRect->bottom - SourceRect->top;
558   SrcWidth = SourceRect->right - SourceRect->left;
559 
560   RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x3);
561   DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 + DestRect->left +
562                       (DestRect->top * DestSurf->lDelta));
563 
564   for(Y = DestRect->top; Y < DestRect->bottom; Y++)
565   {
566     DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 + DestRect->left +
567                         (Y * DestSurf->lDelta));
568     SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
569     for (X = DestRect->left; X < RoundedRight; X += 4, DestBits++)
570     {
571       Dest = *DestBits;
572 
573       SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
574       if (SourceX >= 0 && SourceY >= 0 &&
575           SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
576       {
577         Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
578         if(Source != iTransColor)
579         {
580           Dest &= 0xFFFFFF00;
581           Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFF);
582         }
583       }
584 
585       SourceX = SourceRect->left+(X+1 - DestRect->left) * SrcWidth / DstWidth;
586       if (SourceX >= 0 && SourceY >= 0 &&
587           SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
588       {
589         Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
590         if(Source != iTransColor)
591         {
592           Dest &= 0xFFFF00FF;
593           Dest |= ((XLATEOBJ_iXlate(ColorTranslation, Source) << 8) & 0xFF00);
594         }
595       }
596 
597       SourceX = SourceRect->left+(X+2 - DestRect->left) * SrcWidth / DstWidth;
598       if (SourceX >= 0 && SourceY >= 0 &&
599           SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
600       {
601         Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
602         if(Source != iTransColor)
603         {
604           Dest &= 0xFF00FFFF;
605           Dest |= ((XLATEOBJ_iXlate(ColorTranslation, Source) << 16) & 0xFF0000);
606         }
607       }
608 
609       SourceX = SourceRect->left+(X+3 - DestRect->left) * SrcWidth / DstWidth;
610       if (SourceX >= 0 && SourceY >= 0 &&
611           SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
612       {
613         Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
614         if(Source != iTransColor)
615         {
616           Dest &= 0x00FFFFFF;
617           Dest |= ((XLATEOBJ_iXlate(ColorTranslation, Source) << 24) & 0xFF000000);
618         }
619       }
620 
621       *DestBits = Dest;
622     }
623 
624     if(X < DestRect->right)
625     {
626       for (; X < DestRect->right; X++)
627       {
628         SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
629         if (SourceX >= 0 && SourceY >= 0 &&
630             SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
631         {
632           Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
633           if(Source != iTransColor)
634           {
635             *((BYTE*)DestBits) = (BYTE)(XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFF);
636           }
637         }
638         DestBits = (PULONG)((ULONG_PTR)DestBits + 1);
639       }
640     }
641   }
642 
643   return TRUE;
644 }
645 
646 /* EOF */
647