xref: /reactos/win32ss/gdi/dib/dib32bpp.c (revision 8a978a17)
1 /*
2  * PROJECT:         Win32 subsystem
3  * LICENSE:         See COPYING in the top level directory
4  * FILE:            win32ss/gdi/dib/dib32bpp.c
5  * PURPOSE:         Device Independant Bitmap functions, 32bpp
6  * PROGRAMMERS:     Jason Filby
7  *                  Thomas Bluemel
8  *                  Gregor Anich
9  */
10 
11 #include <win32k.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 VOID
17 DIB_32BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
18 {
19   PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
20   PDWORD addr = (PDWORD)byteaddr + x;
21 
22   *addr = c;
23 }
24 
25 ULONG
26 DIB_32BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
27 {
28   PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
29   PDWORD addr = (PDWORD)byteaddr + x;
30 
31   return (ULONG)(*addr);
32 }
33 
34 VOID
35 DIB_32BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
36 {
37   PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y1 * SurfObj->lDelta;
38   PDWORD addr = (PDWORD)byteaddr + x;
39   LONG lDelta = SurfObj->lDelta >> 2; // >> 2 == / sizeof(DWORD)
40 
41   byteaddr = (PBYTE)addr;
42   while (y1++ < y2)
43   {
44     *addr = (DWORD)c;
45     addr += lDelta;
46   }
47 }
48 
49 BOOLEAN
50 DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInfo)
51 {
52   LONG     i, j, sx, sy, xColor, f1;
53   PBYTE    SourceBits, DestBits, SourceLine, DestLine;
54   PBYTE    SourceBits_4BPP, SourceLine_4BPP;
55   PDWORD   Source32, Dest32;
56 
57   DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
58     + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta)
59     + 4 * BltInfo->DestRect.left;
60 
61   switch (BltInfo->SourceSurface->iBitmapFormat)
62   {
63   case BMF_1BPP:
64 
65     sx = BltInfo->SourcePoint.x;
66     sy = BltInfo->SourcePoint.y;
67 
68     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
69     {
70       sx = BltInfo->SourcePoint.x;
71       for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
72       {
73         if (DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
74         {
75           DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
76         } else {
77           DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
78         }
79         sx++;
80       }
81       sy++;
82     }
83     break;
84 
85   case BMF_4BPP:
86     SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0
87       + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
88       + (BltInfo->SourcePoint.x >> 1);
89 
90     for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
91     {
92       SourceLine_4BPP = SourceBits_4BPP;
93       sx = BltInfo->SourcePoint.x;
94       f1 = sx & 1;
95 
96       for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
97       {
98         xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
99           (*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
100         DIB_32BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
101         if (f1 == 1) {
102           SourceLine_4BPP++;
103           f1 = 0;
104         } else {
105           f1 = 1;
106         }
107         sx++;
108       }
109 
110       SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
111     }
112     break;
113 
114   case BMF_8BPP:
115     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + BltInfo->SourcePoint.x;
116     DestLine = DestBits;
117 
118     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
119     {
120       SourceBits = SourceLine;
121       DestBits = DestLine;
122 
123       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
124       {
125         xColor = *SourceBits;
126         *((PDWORD) DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
127         SourceBits += 1;
128         DestBits += 4;
129       }
130 
131       SourceLine += BltInfo->SourceSurface->lDelta;
132       DestLine += BltInfo->DestSurface->lDelta;
133     }
134     break;
135 
136   case BMF_16BPP:
137     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 2 * BltInfo->SourcePoint.x;
138     DestLine = DestBits;
139 
140     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
141     {
142       SourceBits = SourceLine;
143       DestBits = DestLine;
144 
145       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
146       {
147         xColor = *((PWORD) SourceBits);
148         *((PDWORD) DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
149         SourceBits += 2;
150         DestBits += 4;
151       }
152 
153       SourceLine += BltInfo->SourceSurface->lDelta;
154       DestLine += BltInfo->DestSurface->lDelta;
155     }
156     break;
157 
158   case BMF_24BPP:
159     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
160       + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
161       + 3 * BltInfo->SourcePoint.x;
162     DestLine = DestBits;
163 
164     for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
165     {
166       SourceBits = SourceLine;
167       DestBits = DestLine;
168 
169       for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
170       {
171         xColor = (*(SourceBits + 2) << 0x10) +
172           (*(SourceBits + 1) << 0x08) +
173           (*(SourceBits));
174         *((PDWORD)DestBits) = (DWORD)XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, xColor);
175         SourceBits += 3;
176         DestBits += 4;
177       }
178 
179       SourceLine += BltInfo->SourceSurface->lDelta;
180       DestLine += BltInfo->DestSurface->lDelta;
181     }
182     break;
183 
184   case BMF_32BPP:
185     if (NULL == BltInfo->XlateSourceToDest ||
186       0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
187     {
188       if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
189       {
190         SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
191         for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
192         {
193           RtlMoveMemory(DestBits, SourceBits, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
194           SourceBits += BltInfo->SourceSurface->lDelta;
195           DestBits += BltInfo->DestSurface->lDelta;
196         }
197       }
198       else
199       {
200         SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
201           + ((BltInfo->SourcePoint.y
202           + BltInfo->DestRect.bottom
203           - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta)
204           + 4 * BltInfo->SourcePoint.x;
205         DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 4 * BltInfo->DestRect.left;
206         for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
207         {
208           RtlMoveMemory(DestBits, SourceBits, 4 * (BltInfo->DestRect.right - BltInfo->DestRect.left));
209           SourceBits -= BltInfo->SourceSurface->lDelta;
210           DestBits -= BltInfo->DestSurface->lDelta;
211         }
212       }
213     }
214     else
215     {
216       if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
217       {
218         SourceBits = ((PBYTE)BltInfo->SourceSurface->pvScan0 + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x);
219         for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
220         {
221           if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
222           {
223             Dest32 = (DWORD *) DestBits;
224             Source32 = (DWORD *) SourceBits;
225             for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
226             {
227               *Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
228             }
229           }
230           else
231           {
232             Dest32 = (DWORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
233             Source32 = (DWORD *) SourceBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
234             for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
235             {
236               *Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
237             }
238           }
239           SourceBits += BltInfo->SourceSurface->lDelta;
240           DestBits += BltInfo->DestSurface->lDelta;
241         }
242       }
243       else
244       {
245         SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 + ((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) + 4 * BltInfo->SourcePoint.x;
246         DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 4 * BltInfo->DestRect.left;
247         for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
248         {
249           if (BltInfo->DestRect.left < BltInfo->SourcePoint.x)
250           {
251             Dest32 = (DWORD *) DestBits;
252             Source32 = (DWORD *) SourceBits;
253             for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
254             {
255               *Dest32++ = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32++);
256             }
257           }
258           else
259           {
260             Dest32 = (DWORD *) DestBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
261             Source32 = (DWORD *) SourceBits + (BltInfo->DestRect.right - BltInfo->DestRect.left - 1);
262             for (i = BltInfo->DestRect.right - 1; BltInfo->DestRect.left <= i; i--)
263             {
264               *Dest32-- = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, *Source32--);
265             }
266           }
267           SourceBits -= BltInfo->SourceSurface->lDelta;
268           DestBits -= BltInfo->DestSurface->lDelta;
269         }
270       }
271     }
272     break;
273 
274   default:
275     DPRINT1("DIB_32BPP_Bitblt: Unhandled Source BPP: %u\n", BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
276     return FALSE;
277   }
278 
279   return TRUE;
280 }
281 
282 BOOLEAN
283 DIB_32BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
284                          RECTL*  DestRect,  RECTL *SourceRect,
285                          XLATEOBJ *ColorTranslation, ULONG iTransColor)
286 {
287   LONG X, Y, SourceX, SourceY = 0, wd;
288   ULONG *DestBits, Source = 0;
289 
290   LONG DstHeight;
291   LONG DstWidth;
292   LONG SrcHeight;
293   LONG SrcWidth;
294 
295   DstHeight = DestRect->bottom - DestRect->top;
296   DstWidth = DestRect->right - DestRect->left;
297   SrcHeight = SourceRect->bottom - SourceRect->top;
298   SrcWidth = SourceRect->right - SourceRect->left;
299 
300   DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
301     (DestRect->left << 2) +
302     DestRect->top * DestSurf->lDelta);
303   wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 2);
304 
305   for (Y = DestRect->top; Y < DestRect->bottom; Y++)
306   {
307     SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
308     for (X = DestRect->left; X < DestRect->right; X++, DestBits++)
309     {
310       SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
311       if (SourceX >= 0 && SourceY >= 0 &&
312         SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
313       {
314         Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
315         if ((0x00FFFFFF & Source) != (0x00FFFFFF & iTransColor))
316         {
317           *DestBits = XLATEOBJ_iXlate(ColorTranslation, Source);
318         }
319       }
320     }
321 
322     DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
323   }
324 
325   return TRUE;
326 }
327 
328 typedef union {
329   ULONG ul;
330   struct {
331     UCHAR red;
332     UCHAR green;
333     UCHAR blue;
334     UCHAR alpha;
335   } col;
336 } NICEPIXEL32;
337 
338 static __inline UCHAR
339 Clamp8(ULONG val)
340 {
341   return (val > 255) ? 255 : (UCHAR)val;
342 }
343 
344 BOOLEAN
345 DIB_32BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
346                      RECTL* SourceRect, CLIPOBJ* ClipRegion,
347                      XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
348 {
349   INT Rows, Cols, SrcX, SrcY;
350   register PULONG Dst;
351   BLENDFUNCTION BlendFunc;
352   register NICEPIXEL32 DstPixel, SrcPixel;
353   UCHAR Alpha, SrcBpp;
354 
355   DPRINT("DIB_32BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
356     SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
357     DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
358 
359   BlendFunc = BlendObj->BlendFunction;
360   if (BlendFunc.BlendOp != AC_SRC_OVER)
361   {
362     DPRINT1("BlendOp != AC_SRC_OVER\n");
363     return FALSE;
364   }
365   if (BlendFunc.BlendFlags != 0)
366   {
367     DPRINT1("BlendFlags != 0\n");
368     return FALSE;
369   }
370   if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
371   {
372     DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
373     return FALSE;
374   }
375   if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
376        BitsPerFormat(Source->iBitmapFormat) != 32)
377   {
378     DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
379     return FALSE;
380   }
381 
382   Dst = (PULONG)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
383     (DestRect->left << 2));
384   SrcBpp = BitsPerFormat(Source->iBitmapFormat);
385 
386   Rows = 0;
387    SrcY = SourceRect->top;
388    while (++Rows <= DestRect->bottom - DestRect->top)
389   {
390     Cols = 0;
391     SrcX = SourceRect->left;
392     while (++Cols <= DestRect->right - DestRect->left)
393     {
394       SrcPixel.ul = DIB_GetSource(Source, SrcX, SrcY, ColorTranslation);
395       SrcPixel.col.red = (SrcPixel.col.red * BlendFunc.SourceConstantAlpha) / 255;
396       SrcPixel.col.green = (SrcPixel.col.green * BlendFunc.SourceConstantAlpha)  / 255;
397       SrcPixel.col.blue = (SrcPixel.col.blue * BlendFunc.SourceConstantAlpha) / 255;
398       SrcPixel.col.alpha = (32 == SrcBpp) ?
399                         (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha) / 255 :
400                         BlendFunc.SourceConstantAlpha ;
401 
402       Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
403            SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha ;
404 
405       DstPixel.ul = *Dst;
406       DstPixel.col.red = Clamp8((DstPixel.col.red * (255 - Alpha)) / 255 + SrcPixel.col.red) ;
407       DstPixel.col.green = Clamp8((DstPixel.col.green * (255 - Alpha)) / 255 + SrcPixel.col.green) ;
408       DstPixel.col.blue = Clamp8((DstPixel.col.blue * (255 - Alpha)) / 255 + SrcPixel.col.blue) ;
409       DstPixel.col.alpha = Clamp8((DstPixel.col.alpha * (255 - Alpha)) / 255 + SrcPixel.col.alpha) ;
410       *Dst++ = DstPixel.ul;
411       SrcX = SourceRect->left + (Cols*(SourceRect->right - SourceRect->left))/(DestRect->right - DestRect->left);
412     }
413     Dst = (PULONG)((ULONG_PTR)Dest->pvScan0 + ((DestRect->top + Rows) * Dest->lDelta) +
414                 (DestRect->left << 2));
415     SrcY = SourceRect->top + (Rows*(SourceRect->bottom - SourceRect->top))/(DestRect->bottom - DestRect->top);
416   }
417 
418   return TRUE;
419 }
420 
421 /* EOF */
422