xref: /reactos/win32ss/gdi/dib/alphablend.c (revision 8a978a17)
1 /*
2  * PROJECT:         Win32 subsystem
3  * LICENSE:         See COPYING in the top level directory
4  * FILE:            win32ss/gdi/dib/alphablend.c
5  * PURPOSE:         AlphaBlend implementation suitable for all bit depths
6  * PROGRAMMERS:     Jérôme Gardou
7  */
8 
9 #include <win32k.h>
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 typedef union
15 {
16   ULONG ul;
17   struct
18   {
19     UCHAR red;
20     UCHAR green;
21     UCHAR blue;
22     UCHAR alpha;
23   } col;
24 } NICEPIXEL32;
25 
26 static __inline UCHAR
27 Clamp8(ULONG val)
28 {
29   return (val > 255) ? 255 : (UCHAR)val;
30 }
31 
32 BOOLEAN
33 DIB_XXBPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
34                      RECTL* SourceRect, CLIPOBJ* ClipRegion,
35                      XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
36 {
37   INT DstX, DstY, SrcX, SrcY;
38   BLENDFUNCTION BlendFunc;
39   register NICEPIXEL32 DstPixel32;
40   register NICEPIXEL32 SrcPixel32;
41   UCHAR Alpha, SrcBpp = BitsPerFormat(Source->iBitmapFormat);
42   EXLATEOBJ* pexlo;
43   EXLATEOBJ exloSrcRGB, exloDstRGB, exloRGBSrc;
44   PFN_DIB_PutPixel pfnDibPutPixel = DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel;
45 
46   DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
47     SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
48     DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
49 
50   BlendFunc = BlendObj->BlendFunction;
51   if (BlendFunc.BlendOp != AC_SRC_OVER)
52   {
53     DPRINT1("BlendOp != AC_SRC_OVER\n");
54     return FALSE;
55   }
56   if (BlendFunc.BlendFlags != 0)
57   {
58     DPRINT1("BlendFlags != 0\n");
59     return FALSE;
60   }
61   if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
62   {
63     DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
64     return FALSE;
65   }
66   if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
67     SrcBpp != 32)
68   {
69     DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
70     return FALSE;
71   }
72 
73   if (!ColorTranslation)
74   {
75     DPRINT1("ColorTranslation must not be NULL!\n");
76     return FALSE;
77   }
78 
79   pexlo = CONTAINING_RECORD(ColorTranslation, EXLATEOBJ, xlo);
80   EXLATEOBJ_vInitialize(&exloSrcRGB, pexlo->ppalSrc, &gpalRGB, 0, 0, 0);
81   EXLATEOBJ_vInitialize(&exloDstRGB, pexlo->ppalDst, &gpalRGB, 0, 0, 0);
82   EXLATEOBJ_vInitialize(&exloRGBSrc, &gpalRGB, pexlo->ppalSrc, 0, 0, 0);
83 
84   SrcY = SourceRect->top;
85   DstY = DestRect->top;
86   while ( DstY < DestRect->bottom )
87   {
88     SrcX = SourceRect->left;
89     DstX = DestRect->left;
90     while(DstX < DestRect->right)
91     {
92       SrcPixel32.ul = DIB_GetSource(Source, SrcX, SrcY, &exloSrcRGB.xlo);
93       SrcPixel32.col.red = (SrcPixel32.col.red * BlendFunc.SourceConstantAlpha) / 255;
94       SrcPixel32.col.green = (SrcPixel32.col.green * BlendFunc.SourceConstantAlpha) / 255;
95       SrcPixel32.col.blue = (SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha) / 255;
96 
97       Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
98            (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha) / 255 :
99            BlendFunc.SourceConstantAlpha ;
100 
101       DstPixel32.ul = DIB_GetSource(Dest, DstX, DstY, &exloDstRGB.xlo);
102       DstPixel32.col.red = Clamp8((DstPixel32.col.red * (255 - Alpha)) / 255 + SrcPixel32.col.red) ;
103       DstPixel32.col.green = Clamp8((DstPixel32.col.green * (255 - Alpha)) / 255 + SrcPixel32.col.green) ;
104       DstPixel32.col.blue = Clamp8((DstPixel32.col.blue * (255 - Alpha)) / 255 + SrcPixel32.col.blue) ;
105       DstPixel32.ul = XLATEOBJ_iXlate(&exloRGBSrc.xlo, DstPixel32.ul);
106       pfnDibPutPixel(Dest, DstX, DstY, XLATEOBJ_iXlate(ColorTranslation, DstPixel32.ul));
107 
108       DstX++;
109       SrcX = SourceRect->left + ((DstX-DestRect->left)*(SourceRect->right - SourceRect->left))
110                                             /(DestRect->right-DestRect->left);
111     }
112     DstY++;
113     SrcY = SourceRect->top + ((DstY-DestRect->top)*(SourceRect->bottom - SourceRect->top))
114                                             /(DestRect->bottom-DestRect->top);
115   }
116 
117   EXLATEOBJ_vCleanup(&exloDstRGB);
118   EXLATEOBJ_vCleanup(&exloRGBSrc);
119   EXLATEOBJ_vCleanup(&exloSrcRGB);
120 
121   return TRUE;
122 }
123 
124