diff --git a/reactos/win32ss/gdi/dib/dib.c b/reactos/win32ss/gdi/dib/dib.c index 516b4bd3ae9..21a91078cf6 100644 --- a/reactos/win32ss/gdi/dib/dib.c +++ b/reactos/win32ss/gdi/dib/dib.c @@ -47,7 +47,7 @@ DIB_FUNCTIONS DibFunctionsForBitmapFormat[] = { DIB_16BPP_PutPixel, DIB_16BPP_GetPixel, DIB_16BPP_HLine, DIB_16BPP_VLine, DIB_16BPP_BitBlt, DIB_16BPP_BitBltSrcCopy, DIB_XXBPP_StretchBlt, - DIB_16BPP_TransparentBlt, DIB_16BPP_ColorFill, DIB_XXBPP_AlphaBlend + DIB_16BPP_TransparentBlt, DIB_16BPP_ColorFill, DIB_16BPP_AlphaBlend }, /* BMF_24BPP */ { diff --git a/reactos/win32ss/gdi/dib/dib.h b/reactos/win32ss/gdi/dib/dib.h index 440162a744f..685cd00cc58 100644 --- a/reactos/win32ss/gdi/dib/dib.h +++ b/reactos/win32ss/gdi/dib/dib.h @@ -101,6 +101,7 @@ BOOLEAN DIB_16BPP_BitBlt(PBLTINFO); BOOLEAN DIB_16BPP_BitBltSrcCopy(PBLTINFO); BOOLEAN DIB_16BPP_TransparentBlt(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,XLATEOBJ*,ULONG); BOOLEAN DIB_16BPP_ColorFill(SURFOBJ*, RECTL*, ULONG); +BOOLEAN DIB_16BPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*); VOID DIB_24BPP_PutPixel(SURFOBJ*,LONG,LONG,ULONG); ULONG DIB_24BPP_GetPixel(SURFOBJ*,LONG,LONG); diff --git a/reactos/win32ss/gdi/dib/dib16bpp.c b/reactos/win32ss/gdi/dib/dib16bpp.c index e4f415367a9..713529533f0 100644 --- a/reactos/win32ss/gdi/dib/dib16bpp.c +++ b/reactos/win32ss/gdi/dib/dib16bpp.c @@ -525,4 +525,135 @@ DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, return TRUE; } +typedef union +{ + ULONG ul; + struct + { + UCHAR red; + UCHAR green; + UCHAR blue; + UCHAR alpha; + } col; +} NICEPIXEL32; + +typedef union +{ + USHORT us; + struct + { + USHORT red :5; + USHORT green :6; + USHORT blue :5; + } col; +} NICEPIXEL16; + +static __inline UCHAR +Clamp6(ULONG val) +{ + return (val > 63) ? 63 : (UCHAR)val; +} + +static __inline UCHAR +Clamp5(ULONG val) +{ + return (val > 31) ? 31 : (UCHAR)val; +} + +BOOLEAN +DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect, + RECTL* SourceRect, CLIPOBJ* ClipRegion, + XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj) +{ + INT DstX, DstY, SrcX, SrcY; + BLENDFUNCTION BlendFunc; + NICEPIXEL32 SrcPixel32; + NICEPIXEL16 DstPixel16; + UCHAR Alpha, Alpha6, Alpha5; + EXLATEOBJ* pexlo; + EXLATEOBJ exloSrcRGB; + + DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n", + SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom, + DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); + + BlendFunc = BlendObj->BlendFunction; + if (BlendFunc.BlendOp != AC_SRC_OVER) + { + DPRINT1("BlendOp != AC_SRC_OVER\n"); + return FALSE; + } + if (BlendFunc.BlendFlags != 0) + { + DPRINT1("BlendFlags != 0\n"); + return FALSE; + } + if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0) + { + DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat); + return FALSE; + } + if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 && + (BitsPerFormat(Source->iBitmapFormat) != 32)) + { + DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n"); + return FALSE; + } + + if (!ColorTranslation) + { + DPRINT1("ColorTranslation must not be NULL!\n"); + return FALSE; + } + + pexlo = CONTAINING_RECORD(ColorTranslation, EXLATEOBJ, xlo); + EXLATEOBJ_vInitialize(&exloSrcRGB, pexlo->ppalSrc, &gpalRGB, 0, 0, 0); + + SrcY = SourceRect->top; + DstY = DestRect->top; + while ( DstY < DestRect->bottom ) + { + SrcX = SourceRect->left; + DstX = DestRect->left; + while(DstX < DestRect->right) + { + SrcPixel32.ul = DIB_GetSource(Source, SrcX, SrcY, &exloSrcRGB.xlo); + SrcPixel32.col.red = (SrcPixel32.col.red * BlendFunc.SourceConstantAlpha) / 255; + SrcPixel32.col.green = (SrcPixel32.col.green * BlendFunc.SourceConstantAlpha) / 255; + SrcPixel32.col.blue = (SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha) / 255; + + Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ? + (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha) / 255 : + BlendFunc.SourceConstantAlpha; + + Alpha6 = Alpha >> 2; + Alpha5 = Alpha >> 3; + + DstPixel16.us = DIB_16BPP_GetPixel(Dest, DstX, DstY) & 0xFFFF; + /* Perform bit loss */ + SrcPixel32.col.red >>= 3; + SrcPixel32.col.green >>= 2; + SrcPixel32.col.blue >>= 3; + + /* Do the blend in the right bit depth */ + DstPixel16.col.red = Clamp5((DstPixel16.col.red * (31 - Alpha5)) / 31 + SrcPixel32.col.red); + DstPixel16.col.green = Clamp6((DstPixel16.col.green * (63 - Alpha6)) / 63 + SrcPixel32.col.green); + DstPixel16.col.blue = Clamp5((DstPixel16.col.blue * (31 - Alpha5)) / 31 + SrcPixel32.col.blue); + + DIB_16BPP_PutPixel(Dest, DstX, DstY, DstPixel16.us); + + DstX++; + SrcX = SourceRect->left + ((DstX-DestRect->left)*(SourceRect->right - SourceRect->left)) + /(DestRect->right-DestRect->left); + } + DstY++; + SrcY = SourceRect->top + ((DstY-DestRect->top)*(SourceRect->bottom - SourceRect->top)) + /(DestRect->bottom-DestRect->top); + } + + EXLATEOBJ_vCleanup(&exloSrcRGB); + + return TRUE; +} + /* EOF */