mirror of
https://github.com/reactos/reactos.git
synced 2025-04-20 04:20:46 +00:00

The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
698 lines
20 KiB
C
698 lines
20 KiB
C
/*
|
|
* PROJECT: Win32 subsystem
|
|
* LICENSE: See COPYING in the top level directory
|
|
* FILE: subsystems/win32/win32k/dib/dib16bpp.c
|
|
* PURPOSE: Device Independant Bitmap functions, 16bpp
|
|
* PROGRAMMERS: Jason Filby
|
|
* Thomas Bluemel
|
|
* Gregor Anich
|
|
*/
|
|
|
|
#include <w32k.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
VOID
|
|
DIB_16BPP_PutPixel(SURFOBJ *SurfObj, LONG x, LONG y, ULONG c)
|
|
{
|
|
PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
|
|
PWORD addr = (PWORD)byteaddr + x;
|
|
|
|
*addr = (WORD)c;
|
|
}
|
|
|
|
ULONG
|
|
DIB_16BPP_GetPixel(SURFOBJ *SurfObj, LONG x, LONG y)
|
|
{
|
|
PBYTE byteaddr = (PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta;
|
|
PWORD addr = (PWORD)byteaddr + x;
|
|
return (ULONG)(*addr);
|
|
}
|
|
|
|
VOID
|
|
DIB_16BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
|
|
{
|
|
PDWORD addr = (PDWORD)((PWORD)((PBYTE)SurfObj->pvScan0 + y * SurfObj->lDelta) + x1);
|
|
|
|
#if defined(_M_IX86) && !defined(_MSC_VER)
|
|
/* This is about 10% faster than the generic C code below */
|
|
LONG Count = x2 - x1;
|
|
|
|
__asm__ __volatile__ (
|
|
" cld\n"
|
|
" mov %0, %%eax\n"
|
|
" shl $16, %%eax\n"
|
|
" andl $0xffff, %0\n" /* If the pixel value is "abcd", put "abcdabcd" in %eax */
|
|
" or %0, %%eax\n"
|
|
" mov %2, %%edi\n"
|
|
" test $0x03, %%edi\n" /* Align to fullword boundary */
|
|
" jz 0f\n"
|
|
" stosw\n"
|
|
" dec %1\n"
|
|
" jz 1f\n"
|
|
"0:\n"
|
|
" mov %1,%%ecx\n" /* Setup count of fullwords to fill */
|
|
" shr $1,%%ecx\n"
|
|
" rep stosl\n" /* The actual fill */
|
|
" test $0x01, %1\n" /* One left to do at the right side? */
|
|
" jz 1f\n"
|
|
" stosw\n"
|
|
"1:\n"
|
|
: /* no output */
|
|
: "r"(c), "r"(Count), "m"(addr)
|
|
: "%eax", "%ecx", "%edi");
|
|
#else /* _M_IX86 */
|
|
LONG cx = x1;
|
|
DWORD cc;
|
|
|
|
if (0 != (cx & 0x01))
|
|
{
|
|
*((PWORD) addr) = c;
|
|
cx++;
|
|
addr = (PDWORD)((PWORD)(addr) + 1);
|
|
}
|
|
cc = ((c & 0xffff) << 16) | (c & 0xffff);
|
|
while(cx + 1 < x2)
|
|
{
|
|
*addr++ = cc;
|
|
cx += 2;
|
|
}
|
|
if (cx < x2)
|
|
{
|
|
*((PWORD) addr) = c;
|
|
}
|
|
#endif /* _M_IX86 */
|
|
}
|
|
|
|
|
|
VOID
|
|
DIB_16BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
|
|
{
|
|
#if defined(_M_IX86) && !defined(_MSC_VER)
|
|
asm volatile(
|
|
" testl %2, %2" "\n\t"
|
|
" jle 2f" "\n\t"
|
|
" movl %2, %%ecx" "\n\t"
|
|
" shrl $2, %2" "\n\t"
|
|
" andl $3, %%ecx" "\n\t"
|
|
" jz 1f" "\n\t"
|
|
"0:" "\n\t"
|
|
" movw %%ax, (%0)" "\n\t"
|
|
" addl %1, %0" "\n\t"
|
|
" decl %%ecx" "\n\t"
|
|
" jnz 0b" "\n\t"
|
|
" testl %2, %2" "\n\t"
|
|
" jz 2f" "\n\t"
|
|
"1:" "\n\t"
|
|
" movw %%ax, (%0)" "\n\t"
|
|
" addl %1, %0" "\n\t"
|
|
" movw %%ax, (%0)" "\n\t"
|
|
" addl %1, %0" "\n\t"
|
|
" movw %%ax, (%0)" "\n\t"
|
|
" addl %1, %0" "\n\t"
|
|
" movw %%ax, (%0)" "\n\t"
|
|
" addl %1, %0" "\n\t"
|
|
" decl %2" "\n\t"
|
|
" jnz 1b" "\n\t"
|
|
"2:" "\n\t"
|
|
: /* no output */
|
|
: "r"((PBYTE)SurfObj->pvScan0 + (y1 * SurfObj->lDelta) + (x * sizeof (WORD))),
|
|
"r"(SurfObj->lDelta), "r"(y2 - y1), "a"(c)
|
|
: "cc", "memory", "%ecx");
|
|
#else
|
|
PBYTE byteaddr = (PBYTE)(ULONG_PTR)SurfObj->pvScan0 + y1 * SurfObj->lDelta;
|
|
PWORD addr = (PWORD)byteaddr + x;
|
|
LONG lDelta = SurfObj->lDelta;
|
|
|
|
byteaddr = (PBYTE)addr;
|
|
while(y1++ < y2)
|
|
{
|
|
*addr = (WORD)c;
|
|
|
|
byteaddr += lDelta;
|
|
addr = (PWORD)byteaddr;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
BOOLEAN
|
|
DIB_16BPP_BitBltSrcCopy(PBLTINFO BltInfo)
|
|
{
|
|
LONG i, j, sx, sy, xColor, f1;
|
|
PBYTE SourceBits, DestBits, SourceLine, DestLine;
|
|
PBYTE SourceBits_4BPP, SourceLine_4BPP;
|
|
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) + 2 * BltInfo->DestRect.left;
|
|
|
|
switch(BltInfo->SourceSurface->iBitmapFormat)
|
|
{
|
|
case BMF_1BPP:
|
|
sx = BltInfo->SourcePoint.x;
|
|
sy = BltInfo->SourcePoint.y;
|
|
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
|
|
{
|
|
sx = BltInfo->SourcePoint.x;
|
|
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
|
|
{
|
|
if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
|
|
{
|
|
DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
|
|
XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
|
|
}
|
|
else
|
|
{
|
|
DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j,
|
|
XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
|
|
}
|
|
sx++;
|
|
}
|
|
sy++;
|
|
}
|
|
break;
|
|
|
|
case BMF_4BPP:
|
|
SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 +
|
|
(BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
|
|
(BltInfo->SourcePoint.x >> 1);
|
|
|
|
for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
|
|
{
|
|
SourceLine_4BPP = SourceBits_4BPP;
|
|
sx = BltInfo->SourcePoint.x;
|
|
f1 = sx & 1;
|
|
|
|
for (i=BltInfo->DestRect.left; i<BltInfo->DestRect.right; i++)
|
|
{
|
|
xColor = XLATEOBJ_iXlate(BltInfo->XlateSourceToDest,
|
|
(*SourceLine_4BPP & altnotmask[f1]) >> (4 * (1 - f1)));
|
|
DIB_16BPP_PutPixel(BltInfo->DestSurface, i, j, xColor);
|
|
if(f1 == 1)
|
|
{
|
|
SourceLine_4BPP++;
|
|
f1 = 0;
|
|
}
|
|
else
|
|
{
|
|
f1 = 1;
|
|
}
|
|
sx++;
|
|
}
|
|
SourceBits_4BPP += BltInfo->SourceSurface->lDelta;
|
|
}
|
|
break;
|
|
|
|
case BMF_8BPP:
|
|
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
|
|
(BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
|
|
BltInfo->SourcePoint.x;
|
|
DestLine = DestBits;
|
|
|
|
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
|
|
{
|
|
SourceBits = SourceLine;
|
|
DestBits = DestLine;
|
|
|
|
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
|
|
{
|
|
*((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
|
|
BltInfo->XlateSourceToDest, *SourceBits);
|
|
SourceBits += 1;
|
|
DestBits += 2;
|
|
}
|
|
|
|
SourceLine += BltInfo->SourceSurface->lDelta;
|
|
DestLine += BltInfo->DestSurface->lDelta;
|
|
}
|
|
break;
|
|
|
|
case BMF_16BPP:
|
|
if (NULL == BltInfo->XlateSourceToDest || 0 !=
|
|
(BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
|
|
{
|
|
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
|
|
{
|
|
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
|
|
(BltInfo->SourcePoint.y *
|
|
BltInfo->SourceSurface->lDelta) + 2 *
|
|
BltInfo->SourcePoint.x;
|
|
|
|
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
|
|
{
|
|
RtlMoveMemory(DestBits, SourceBits,
|
|
2 * (BltInfo->DestRect.right -
|
|
BltInfo->DestRect.left));
|
|
|
|
SourceBits += BltInfo->SourceSurface->lDelta;
|
|
DestBits += BltInfo->DestSurface->lDelta;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 +
|
|
((BltInfo->SourcePoint.y + BltInfo->DestRect.bottom -
|
|
BltInfo->DestRect.top - 1) *
|
|
BltInfo->SourceSurface->lDelta) + 2 *
|
|
BltInfo->SourcePoint.x;
|
|
|
|
DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 +
|
|
((BltInfo->DestRect.bottom - 1) *
|
|
BltInfo->DestSurface->lDelta) + 2 *
|
|
BltInfo->DestRect.left;
|
|
|
|
for (j = BltInfo->DestRect.bottom - 1;
|
|
BltInfo->DestRect.top <= j; j--)
|
|
{
|
|
RtlMoveMemory(DestBits, SourceBits, 2 *
|
|
(BltInfo->DestRect.right -
|
|
BltInfo->DestRect.left));
|
|
|
|
SourceBits -= BltInfo->SourceSurface->lDelta;
|
|
DestBits -= BltInfo->DestSurface->lDelta;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
|
|
{
|
|
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
|
|
(BltInfo->SourcePoint.y *
|
|
BltInfo->SourceSurface->lDelta) + 2 *
|
|
BltInfo->SourcePoint.x;
|
|
|
|
DestLine = DestBits;
|
|
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
|
|
{
|
|
SourceBits = SourceLine;
|
|
DestBits = DestLine;
|
|
for (i = BltInfo->DestRect.left; i <
|
|
BltInfo->DestRect.right; i++)
|
|
{
|
|
*((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
|
|
BltInfo->XlateSourceToDest,
|
|
*((WORD *)SourceBits));
|
|
SourceBits += 2;
|
|
DestBits += 2;
|
|
}
|
|
SourceLine += BltInfo->SourceSurface->lDelta;
|
|
DestLine += BltInfo->DestSurface->lDelta;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
|
|
((BltInfo->SourcePoint.y +
|
|
BltInfo->DestRect.bottom -
|
|
BltInfo->DestRect.top - 1) *
|
|
BltInfo->SourceSurface->lDelta) + 2 *
|
|
BltInfo->SourcePoint.x;
|
|
|
|
DestLine = (PBYTE)BltInfo->DestSurface->pvScan0 +
|
|
((BltInfo->DestRect.bottom - 1) *
|
|
BltInfo->DestSurface->lDelta) + 2 *
|
|
BltInfo->DestRect.left;
|
|
|
|
for (j = BltInfo->DestRect.bottom - 1;
|
|
BltInfo->DestRect.top <= j; j--)
|
|
{
|
|
SourceBits = SourceLine;
|
|
DestBits = DestLine;
|
|
for (i = BltInfo->DestRect.left; i <
|
|
BltInfo->DestRect.right; i++)
|
|
{
|
|
*((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
|
|
BltInfo->XlateSourceToDest,
|
|
*((WORD *)SourceBits));
|
|
SourceBits += 2;
|
|
DestBits += 2;
|
|
}
|
|
SourceLine -= BltInfo->SourceSurface->lDelta;
|
|
DestLine -= BltInfo->DestSurface->lDelta;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case BMF_24BPP:
|
|
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
|
|
(BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
|
|
3 * BltInfo->SourcePoint.x;
|
|
|
|
DestLine = DestBits;
|
|
|
|
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
|
|
{
|
|
SourceBits = SourceLine;
|
|
DestBits = DestLine;
|
|
|
|
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
|
|
{
|
|
xColor = (*(SourceBits + 2) << 0x10) +
|
|
(*(SourceBits + 1) << 0x08) + (*(SourceBits));
|
|
|
|
*((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
|
|
BltInfo->XlateSourceToDest, xColor);
|
|
|
|
SourceBits += 3;
|
|
DestBits += 2;
|
|
}
|
|
SourceLine += BltInfo->SourceSurface->lDelta;
|
|
DestLine += BltInfo->DestSurface->lDelta;
|
|
}
|
|
break;
|
|
|
|
case BMF_32BPP:
|
|
SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 +
|
|
(BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) +
|
|
4 * BltInfo->SourcePoint.x;
|
|
|
|
DestLine = DestBits;
|
|
|
|
for (j = BltInfo->DestRect.top; j < BltInfo->DestRect.bottom; j++)
|
|
{
|
|
SourceBits = SourceLine;
|
|
DestBits = DestLine;
|
|
|
|
for (i = BltInfo->DestRect.left; i < BltInfo->DestRect.right; i++)
|
|
{
|
|
*((WORD *)DestBits) = (WORD)XLATEOBJ_iXlate(
|
|
BltInfo->XlateSourceToDest,
|
|
*((PDWORD) SourceBits));
|
|
SourceBits += 4;
|
|
DestBits += 2;
|
|
}
|
|
|
|
SourceLine += BltInfo->SourceSurface->lDelta;
|
|
DestLine += BltInfo->DestSurface->lDelta;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
DPRINT1("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n",
|
|
BitsPerFormat(BltInfo->SourceSurface->iBitmapFormat));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* Optimize for bitBlt */
|
|
BOOLEAN
|
|
DIB_16BPP_ColorFill(SURFOBJ* DestSurface, RECTL* DestRect, ULONG color)
|
|
{
|
|
ULONG DestY;
|
|
|
|
#if defined(_M_IX86) && !defined(_MSC_VER)
|
|
/* This is about 10% faster than the generic C code below */
|
|
ULONG delta = DestSurface->lDelta;
|
|
ULONG width = (DestRect->right - DestRect->left) ;
|
|
PULONG pos = (PULONG) ((PBYTE)DestSurface->pvScan0 + DestRect->top * delta + (DestRect->left<<1));
|
|
color = (color&0xffff); /* If the color value is "abcd", put "abcdabcd" into color */
|
|
color += (color<<16);
|
|
|
|
for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
|
|
{
|
|
__asm__ __volatile__ (
|
|
" cld\n"
|
|
" mov %1,%%ebx\n"
|
|
" mov %2,%%edi\n"
|
|
" test $0x03, %%edi\n" /* Align to fullword boundary */
|
|
" jz .FL1\n"
|
|
" stosw\n"
|
|
" dec %%ebx\n"
|
|
" jz .FL2\n"
|
|
".FL1:\n"
|
|
" mov %%ebx,%%ecx\n" /* Setup count of fullwords to fill */
|
|
" shr $1,%%ecx\n"
|
|
" rep stosl\n" /* The actual fill */
|
|
" test $0x01, %%ebx\n" /* One left to do at the right side? */
|
|
" jz .FL2\n"
|
|
" stosw\n"
|
|
".FL2:\n"
|
|
:
|
|
: "a" (color), "r" (width), "m" (pos)
|
|
: "%ecx", "%ebx", "%edi");
|
|
pos =(PULONG)((ULONG_PTR)pos + delta);
|
|
}
|
|
#else /* _M_IX86 */
|
|
|
|
for (DestY = DestRect->top; DestY< DestRect->bottom; DestY++)
|
|
{
|
|
DIB_16BPP_HLine (DestSurface, DestRect->left, DestRect->right, DestY, color);
|
|
}
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf,
|
|
RECTL* DestRect, RECTL *SourceRect,
|
|
XLATEOBJ *ColorTranslation, ULONG iTransColor)
|
|
{
|
|
ULONG RoundedRight, X, Y, SourceX = 0, SourceY = 0, Source, wd, Dest;
|
|
ULONG *DestBits;
|
|
|
|
LONG DstHeight;
|
|
LONG DstWidth;
|
|
LONG SrcHeight;
|
|
LONG SrcWidth;
|
|
|
|
DstHeight = DestRect->bottom - DestRect->top;
|
|
DstWidth = DestRect->right - DestRect->left;
|
|
SrcHeight = SourceRect->bottom - SourceRect->top;
|
|
SrcWidth = SourceRect->right - SourceRect->left;
|
|
|
|
RoundedRight = DestRect->right - ((DestRect->right - DestRect->left) & 0x1);
|
|
DestBits = (ULONG*)((PBYTE)DestSurf->pvScan0 +
|
|
(DestRect->left << 1) +
|
|
DestRect->top * DestSurf->lDelta);
|
|
wd = DestSurf->lDelta - ((DestRect->right - DestRect->left) << 1);
|
|
|
|
for(Y = DestRect->top; Y < DestRect->bottom; Y++)
|
|
{
|
|
SourceY = SourceRect->top+(Y - DestRect->top) * SrcHeight / DstHeight;
|
|
for(X = DestRect->left; X < RoundedRight; X += 2, DestBits++, SourceX += 2)
|
|
{
|
|
Dest = *DestBits;
|
|
|
|
SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
|
|
if (SourceX >= 0 && SourceY >= 0 &&
|
|
SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
|
|
{
|
|
Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
|
|
if(Source != iTransColor)
|
|
{
|
|
Dest &= 0xFFFF0000;
|
|
Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) & 0xFFFF);
|
|
}
|
|
}
|
|
|
|
SourceX = SourceRect->left+(X+1 - DestRect->left) * SrcWidth / DstWidth;
|
|
if (SourceX >= 0 && SourceY >= 0 &&
|
|
SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
|
|
{
|
|
Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
|
|
if(Source != iTransColor)
|
|
{
|
|
Dest &= 0xFFFF;
|
|
Dest |= (XLATEOBJ_iXlate(ColorTranslation, Source) << 16);
|
|
}
|
|
}
|
|
|
|
*DestBits = Dest;
|
|
}
|
|
|
|
if(X < DestRect->right)
|
|
{
|
|
SourceX = SourceRect->left+(X - DestRect->left) * SrcWidth / DstWidth;
|
|
if (SourceX >= 0 && SourceY >= 0 &&
|
|
SourceSurf->sizlBitmap.cx > SourceX && SourceSurf->sizlBitmap.cy > SourceY)
|
|
{
|
|
Source = DIB_GetSourceIndex(SourceSurf, SourceX, SourceY);
|
|
if(Source != iTransColor)
|
|
{
|
|
*((USHORT*)DestBits) = (USHORT)XLATEOBJ_iXlate(ColorTranslation,
|
|
Source);
|
|
}
|
|
}
|
|
|
|
DestBits = (PULONG)((ULONG_PTR)DestBits + 2);
|
|
}
|
|
|
|
DestBits = (ULONG*)((ULONG_PTR)DestBits + wd);
|
|
}
|
|
|
|
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,
|
|
green:6,
|
|
blue:5;
|
|
} col;
|
|
} NICEPIXEL16;
|
|
|
|
static __inline UCHAR
|
|
Clamp5(ULONG val)
|
|
{
|
|
return (val > 31) ? 31 : val;
|
|
}
|
|
|
|
static __inline UCHAR
|
|
Clamp8(ULONG val)
|
|
{
|
|
return (val > 255) ? 255 : val;
|
|
}
|
|
|
|
static __inline UCHAR
|
|
Clamp6(ULONG val)
|
|
{
|
|
return (val > 63) ? 63 : val;
|
|
}
|
|
|
|
BOOLEAN
|
|
DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
|
|
RECTL* SourceRect, CLIPOBJ* ClipRegion,
|
|
XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
|
|
{
|
|
INT Rows, Cols, SrcX, SrcY;
|
|
register PUSHORT Dst;
|
|
ULONG DstDelta;
|
|
BLENDFUNCTION BlendFunc;
|
|
register NICEPIXEL16 SrcPixel16;
|
|
register NICEPIXEL16 DstPixel16;
|
|
register NICEPIXEL32 SrcPixel32;
|
|
register NICEPIXEL32 DstPixel32;
|
|
UCHAR Alpha, SrcBpp;
|
|
EXLATEOBJ *pexlo;
|
|
EXLATEOBJ exloDst2Src;
|
|
|
|
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);
|
|
|
|
ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
|
|
DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
|
|
|
|
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(&exloDst2Src, pexlo->ppalDst, pexlo->ppalSrc, 0, 0, 0);
|
|
|
|
Dst = (PUSHORT)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
|
|
(DestRect->left << 1));
|
|
DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) << 1);
|
|
SrcBpp = BitsPerFormat(Source->iBitmapFormat);
|
|
|
|
Rows = DestRect->bottom - DestRect->top;
|
|
SrcY = SourceRect->top;
|
|
while (--Rows >= 0)
|
|
{
|
|
Cols = DestRect->right - DestRect->left;
|
|
SrcX = SourceRect->left;
|
|
while (--Cols >= 0)
|
|
{
|
|
if (SrcBpp <= 16)
|
|
{
|
|
SrcPixel16.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
|
|
SrcPixel32.col.red = (SrcPixel16.col.red << 3);
|
|
SrcPixel32.col.green = (SrcPixel16.col.green << 2);
|
|
SrcPixel32.col.blue = (SrcPixel16.col.blue << 3);
|
|
|
|
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;
|
|
SrcPixel32.col.alpha = (SrcBpp == 32) ?
|
|
(SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) :
|
|
BlendFunc.SourceConstantAlpha;
|
|
|
|
Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
|
|
SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
|
|
|
|
DstPixel16.us = *Dst;
|
|
DstPixel16.col.red = Clamp5(DstPixel16.col.red * (255 - Alpha) / 255 +
|
|
(SrcPixel32.col.red >> 3));
|
|
|
|
DstPixel16.col.green = Clamp6(DstPixel16.col.green * (255 - Alpha) / 255 +
|
|
(SrcPixel32.col.green >> 2));
|
|
|
|
DstPixel16.col.blue = Clamp5(DstPixel16.col.blue * (255 - Alpha) / 255 +
|
|
(SrcPixel32.col.blue >> 3));
|
|
|
|
*Dst++ = DstPixel16.us;
|
|
}
|
|
else
|
|
{
|
|
SrcPixel32.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
|
|
|
|
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;
|
|
SrcPixel32.col.alpha = (SrcBpp == 32) ?
|
|
(SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) :
|
|
BlendFunc.SourceConstantAlpha;
|
|
|
|
Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
|
|
SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
|
|
|
|
DstPixel32.ul = XLATEOBJ_iXlate(&exloDst2Src.xlo, *Dst);
|
|
SrcPixel32.col.red = Clamp8(DstPixel32.col.red * (255 - Alpha) / 255 + SrcPixel32.col.red);
|
|
SrcPixel32.col.green = Clamp8(DstPixel32.col.green * (255 - Alpha) / 255 + SrcPixel32.col.green);
|
|
SrcPixel32.col.blue = Clamp8(DstPixel32.col.blue * (255 - Alpha) / 255 + SrcPixel32.col.blue);
|
|
*Dst++ = XLATEOBJ_iXlate(ColorTranslation, SrcPixel32.ul);
|
|
}
|
|
}
|
|
|
|
Dst = (PUSHORT)((ULONG_PTR)Dst + DstDelta);
|
|
SrcY++;
|
|
}
|
|
|
|
EXLATEOBJ_vCleanup(&exloDst2Src);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* EOF */
|