From 4b8fc8e4e49bd89e6248ef763a727a874334011d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Fri, 14 May 2004 22:56:18 +0000 Subject: [PATCH] Implement complex clipping for StretchBlt svn path=/trunk/; revision=9388 --- reactos/subsys/win32k/dib/dib.h | 18 ++- reactos/subsys/win32k/dib/dib16bpp.c | 146 ++++++++++++++----- reactos/subsys/win32k/dib/dib1bpp.c | 5 +- reactos/subsys/win32k/dib/dib24bpp.c | 5 +- reactos/subsys/win32k/dib/dib32bpp.c | 141 ++++++++++++++----- reactos/subsys/win32k/dib/dib4bpp.c | 5 +- reactos/subsys/win32k/dib/dib8bpp.c | 144 ++++++++++++++----- reactos/subsys/win32k/eng/bitblt.c | 200 +++++---------------------- reactos/subsys/win32k/eng/clip.c | 121 +++++++++++++++- reactos/subsys/win32k/eng/clip.h | 9 ++ reactos/subsys/win32k/eng/surface.c | 5 +- reactos/subsys/win32k/include/tags.h | 1 + 12 files changed, 516 insertions(+), 284 deletions(-) diff --git a/reactos/subsys/win32k/dib/dib.h b/reactos/subsys/win32k/dib/dib.h index dad5d27f9c6..24a07cdb767 100644 --- a/reactos/subsys/win32k/dib/dib.h +++ b/reactos/subsys/win32k/dib/dib.h @@ -21,7 +21,8 @@ BOOLEAN DIB_1BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrigin, - XLATEOBJ *ColorTranslation, ULONG Mode); + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode); BOOLEAN DIB_1BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, PSURFGDI DestGDI, PSURFGDI SourceGDI, RECTL* DestRect, POINTL *SourcePoint, @@ -40,7 +41,8 @@ BOOLEAN DIB_4BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrigin, - XLATEOBJ *ColorTranslation, ULONG Mode); + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode); BOOLEAN DIB_4BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, PSURFGDI DestGDI, PSURFGDI SourceGDI, RECTL* DestRect, POINTL *SourcePoint, @@ -59,7 +61,8 @@ BOOLEAN DIB_8BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrigin, - XLATEOBJ *ColorTranslation, ULONG Mode); + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode); BOOLEAN DIB_8BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, PSURFGDI DestGDI, PSURFGDI SourceGDI, RECTL* DestRect, POINTL *SourcePoint, @@ -78,7 +81,8 @@ BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrigin, - XLATEOBJ *ColorTranslation, ULONG Mode); + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode); BOOLEAN DIB_16BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, PSURFGDI DestGDI, PSURFGDI SourceGDI, RECTL* DestRect, POINTL *SourcePoint, @@ -97,7 +101,8 @@ BOOLEAN DIB_24BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrigin, - XLATEOBJ *ColorTranslation, ULONG Mode); + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode); BOOLEAN DIB_24BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, PSURFGDI DestGDI, PSURFGDI SourceGDI, RECTL* DestRect, POINTL *SourcePoint, @@ -116,7 +121,8 @@ BOOLEAN DIB_32BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrigin, - XLATEOBJ *ColorTranslation, ULONG Mode); + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode); BOOLEAN DIB_32BPP_TransparentBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, PSURFGDI DestGDI, PSURFGDI SourceGDI, RECTL* DestRect, POINTL *SourcePoint, diff --git a/reactos/subsys/win32k/dib/dib16bpp.c b/reactos/subsys/win32k/dib/dib16bpp.c index abeafbd808d..21ff5cd0b42 100644 --- a/reactos/subsys/win32k/dib/dib16bpp.c +++ b/reactos/subsys/win32k/dib/dib16bpp.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dib16bpp.c,v 1.31 2004/05/10 17:07:17 weiden Exp $ */ +/* $Id: dib16bpp.c,v 1.32 2004/05/14 22:56:17 gvg Exp $ */ #include VOID @@ -256,7 +256,7 @@ DIB_16BPP_BitBltSrcCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, break; default: - DbgPrint("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); + DPRINT1("DIB_16BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); return FALSE; } @@ -468,26 +468,84 @@ void ScaleLineAvg16(PIXEL *Target, PIXEL *Source, int SrcWidth, int TgtWidth) *Target++ = *Source; } -//NOTE: If you change something here, please do the same in other dibXXbpp.c files! -void ScaleRectAvg16(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight, - int TgtWidth, int TgtHeight, int srcPitch, int dstPitch) +static BOOLEAN +FinalCopy16(PIXEL *Target, PIXEL *Source, PSPAN ClipSpans, UINT ClipSpansCount, UINT *SpanIndex, + UINT DestY, RECTL *DestRect) { - int NumPixels = TgtHeight; - int IntPart = ((SrcHeight / TgtHeight) * srcPitch) >> 1; //(SrcHeight / TgtHeight) * SrcWidth; - int FractPart = SrcHeight % TgtHeight; - int Mid = TgtHeight >> 1; + LONG Left, Right; + + while (ClipSpans[*SpanIndex].Y < DestY + || (ClipSpans[*SpanIndex].Y == DestY + && ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width < DestRect->left)) + { + (*SpanIndex)++; + if (ClipSpansCount <= *SpanIndex) + { + /* No more spans, everything else is clipped away, we're done */ + return FALSE; + } + } + while (ClipSpans[*SpanIndex].Y == DestY) + { + if (ClipSpans[*SpanIndex].X < DestRect->right) + { + Left = max(ClipSpans[*SpanIndex].X, DestRect->left); + Right = min(ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width, DestRect->right); + memcpy(Target + Left - DestRect->left, Source + Left - DestRect->left, + (Right - Left) * sizeof(PIXEL)); + } + (*SpanIndex)++; + if (ClipSpansCount <= *SpanIndex) + { + /* No more spans, everything else is clipped away, we're done */ + return FALSE; + } + } + + return TRUE; +} + +//NOTE: If you change something here, please do the same in other dibXXbpp.c files! +BOOLEAN ScaleRectAvg16(SURFGDI *DestGDI, SURFGDI *SourceGDI, + RECTL* DestRect, RECTL *SourceRect, + POINTL* MaskOrigin, POINTL BrushOrigin, + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode) +{ + int NumPixels = DestRect->bottom - DestRect->top; + int IntPart = (((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * SourceGDI->SurfObj.lDelta) >> 1; /* ((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * (SourceRect->right - SourceRect->left); */ + int FractPart = (SourceRect->bottom - SourceRect->top) % (DestRect->bottom - DestRect->top); + int Mid = (DestRect->bottom - DestRect->top) >> 1; int E = 0; int skip; PIXEL *ScanLine, *ScanLineAhead; PIXEL *PrevSource = NULL; PIXEL *PrevSourceAhead = NULL; + PIXEL *Target = (PIXEL *) (DestGDI->SurfObj.pvScan0 + (DestRect->top * DestGDI->SurfObj.lDelta) + 2 * DestRect->left); + PIXEL *Source = (PIXEL *) (SourceGDI->SurfObj.pvScan0 + (SourceRect->top * SourceGDI->SurfObj.lDelta) + 2 * SourceRect->left); + PSPAN ClipSpans; + UINT ClipSpansCount; + UINT SpanIndex; + LONG DestY; - skip = (TgtHeight < SrcHeight) ? 0 : (TgtHeight / (2*SrcHeight) + 1); + if (! ClipobjToSpans(&ClipSpans, &ClipSpansCount, ClipRegion, DestRect)) + { + return FALSE; + } + if (0 == ClipSpansCount) + { + /* No clip spans == empty clipping region, everything clipped away */ + ASSERT(NULL == ClipSpans); + return TRUE; + } + skip = (DestRect->bottom - DestRect->top < SourceRect->bottom - SourceRect->top) ? 0 : ((DestRect->bottom - DestRect->top) / (2 * (SourceRect->bottom - SourceRect->top)) + 1); NumPixels -= skip; - ScanLine = (PIXEL*)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); // FIXME: Should we use PagedPool here? - ScanLineAhead = (PIXEL *)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); + ScanLine = (PIXEL*)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL)); + ScanLineAhead = (PIXEL *)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL)); + DestY = DestRect->top; + SpanIndex = 0; while (NumPixels-- > 0) { if (Source != PrevSource) { if (Source == PrevSourceAhead) { @@ -499,38 +557,57 @@ void ScaleRectAvg16(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight, ScanLine = ScanLineAhead; ScanLineAhead = tmp; } else { - ScaleLineAvg16(ScanLine, Source, SrcWidth, TgtWidth); + ScaleLineAvg16(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left); } /* if */ PrevSource = Source; } /* if */ - if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + srcPitch)) { + if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta)) { int x; - ScaleLineAvg16(ScanLineAhead, (PIXEL *)((BYTE *)Source + srcPitch), SrcWidth, TgtWidth); - for (x = 0; x < TgtWidth; x++) + ScaleLineAvg16(ScanLineAhead, (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta), SourceRect->right - SourceRect->left, DestRect->right - DestRect->left); + for (x = 0; x < DestRect->right - DestRect->left; x++) ScanLine[x] = average16(ScanLine[x], ScanLineAhead[x]); - PrevSourceAhead = (PIXEL *)((BYTE *)Source + srcPitch); + PrevSourceAhead = (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta); } /* if */ - - memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); - Target = (PIXEL *)((BYTE *)Target + dstPitch); + + if (! FinalCopy16(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect)) + { + /* No more spans, everything else is clipped away, we're done */ + ExFreePool(ClipSpans); + ExFreePool(ScanLine); + ExFreePool(ScanLineAhead); + return TRUE; + } + DestY++; + Target = (PIXEL *)((BYTE *)Target + DestGDI->SurfObj.lDelta); Source += IntPart; E += FractPart; - if (E >= TgtHeight) { - E -= TgtHeight; - Source = (PIXEL *)((BYTE *)Source + srcPitch); + if (E >= DestRect->bottom - DestRect->top) { + E -= DestRect->bottom - DestRect->top; + Source = (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta); } /* if */ } /* while */ if (skip > 0 && Source != PrevSource) - ScaleLineAvg16(ScanLine, Source, SrcWidth, TgtWidth); + ScaleLineAvg16(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left); while (skip-- > 0) { - memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); - Target = (PIXEL *)((BYTE *)Target + dstPitch); + if (! FinalCopy16(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect)) + { + /* No more spans, everything else is clipped away, we're done */ + ExFreePool(ClipSpans); + ExFreePool(ScanLine); + ExFreePool(ScanLineAhead); + return TRUE; + } + DestY++; + Target = (PIXEL *)((BYTE *)Target + DestGDI->SurfObj.lDelta); } /* while */ + ExFreePool(ClipSpans); ExFreePool(ScanLine); ExFreePool(ScanLineAhead); + + return TRUE; } //NOTE: If you change something here, please do the same in other dibXXbpp.c files! @@ -538,11 +615,10 @@ BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrigin, - XLATEOBJ *ColorTranslation, ULONG Mode) + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode) { - BYTE *SourceLine, *DestLine; - - DbgPrint("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n", + DPRINT("DIB_16BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n", SourceGDI->BitsPerPixel, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); @@ -561,12 +637,8 @@ BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, break; case 16: - SourceLine = SourceSurf->pvScan0 + (SourceRect->top * SourceSurf->lDelta) + 2 * SourceRect->left; - DestLine = DestSurf->pvScan0 + (DestRect->top * DestSurf->lDelta) + 2 * DestRect->left; - - ScaleRectAvg16((PIXEL *)DestLine, (PIXEL *)SourceLine, - SourceRect->right-SourceRect->left, SourceRect->bottom-SourceRect->top, - DestRect->right-DestRect->left, DestRect->bottom-DestRect->top, SourceSurf->lDelta, DestSurf->lDelta); + return ScaleRectAvg16(DestGDI, SourceGDI, DestRect, SourceRect, MaskOrigin, BrushOrigin, + ClipRegion, ColorTranslation, Mode); break; case 24: @@ -578,7 +650,7 @@ BOOLEAN DIB_16BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, break; default: - DbgPrint("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); + DPRINT1("DIB_16BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); return FALSE; } diff --git a/reactos/subsys/win32k/dib/dib1bpp.c b/reactos/subsys/win32k/dib/dib1bpp.c index 795f2241df0..996d31b245b 100644 --- a/reactos/subsys/win32k/dib/dib1bpp.c +++ b/reactos/subsys/win32k/dib/dib1bpp.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dib1bpp.c,v 1.27 2004/05/10 17:07:17 weiden Exp $ */ +/* $Id: dib1bpp.c,v 1.28 2004/05/14 22:56:17 gvg Exp $ */ #include VOID @@ -515,7 +515,8 @@ DIB_1BPP_StretchBlt ( SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrigin, - XLATEOBJ *ColorTranslation, ULONG Mode) + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode) { DbgPrint("DIB_1BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel); return FALSE; diff --git a/reactos/subsys/win32k/dib/dib24bpp.c b/reactos/subsys/win32k/dib/dib24bpp.c index 2e0cdb31754..22336937cfe 100644 --- a/reactos/subsys/win32k/dib/dib24bpp.c +++ b/reactos/subsys/win32k/dib/dib24bpp.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dib24bpp.c,v 1.26 2004/05/10 17:07:17 weiden Exp $ */ +/* $Id: dib24bpp.c,v 1.27 2004/05/14 22:56:17 gvg Exp $ */ #include VOID @@ -345,7 +345,8 @@ BOOLEAN DIB_24BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrigin, - XLATEOBJ *ColorTranslation, ULONG Mode) + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode) { DbgPrint("DIB_24BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel); return FALSE; diff --git a/reactos/subsys/win32k/dib/dib32bpp.c b/reactos/subsys/win32k/dib/dib32bpp.c index 577d3dc30b4..f33c9d5cead 100644 --- a/reactos/subsys/win32k/dib/dib32bpp.c +++ b/reactos/subsys/win32k/dib/dib32bpp.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dib32bpp.c,v 1.26 2004/05/10 17:07:17 weiden Exp $ */ +/* $Id: dib32bpp.c,v 1.27 2004/05/14 22:56:17 gvg Exp $ */ #include VOID @@ -278,7 +278,7 @@ DIB_32BPP_BitBltSrcCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, break; default: - DbgPrint("DIB_32BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); + DPRINT1("DIB_32BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); return FALSE; } @@ -437,27 +437,85 @@ void ScaleLineAvg32(PIXEL *Target, PIXEL *Source, int SrcWidth, int TgtWidth) while (skip-- > 0) *Target++ = *Source; } + +static BOOLEAN +FinalCopy32(PIXEL *Target, PIXEL *Source, PSPAN ClipSpans, UINT ClipSpansCount, UINT *SpanIndex, + UINT DestY, RECTL *DestRect) +{ + LONG Left, Right; + + while (ClipSpans[*SpanIndex].Y < DestY + || (ClipSpans[*SpanIndex].Y == DestY + && ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width < DestRect->left)) + { + (*SpanIndex)++; + if (ClipSpansCount <= *SpanIndex) + { + /* No more spans, everything else is clipped away, we're done */ + return FALSE; + } + } + while (ClipSpans[*SpanIndex].Y == DestY) + { + if (ClipSpans[*SpanIndex].X < DestRect->right) + { + Left = max(ClipSpans[*SpanIndex].X, DestRect->left); + Right = min(ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width, DestRect->right); + memcpy(Target + Left - DestRect->left, Source + Left - DestRect->left, + (Right - Left) * sizeof(PIXEL)); + } + (*SpanIndex)++; + if (ClipSpansCount <= *SpanIndex) + { + /* No more spans, everything else is clipped away, we're done */ + return FALSE; + } + } + + return TRUE; +} //NOTE: If you change something here, please do the same in other dibXXbpp.c files! -void ScaleRectAvg32(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight, - int TgtWidth, int TgtHeight, int srcPitch, int dstPitch) +BOOLEAN ScaleRectAvg32(SURFGDI *DestGDI, SURFGDI *SourceGDI, + RECTL* DestRect, RECTL *SourceRect, + POINTL* MaskOrigin, POINTL BrushOrigin, + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode) { - int NumPixels = TgtHeight; - int IntPart = ((SrcHeight / TgtHeight) * srcPitch) / 4; //(SrcHeight / TgtHeight) * SrcWidth; - int FractPart = SrcHeight % TgtHeight; - int Mid = TgtHeight >> 1; + int NumPixels = DestRect->bottom - DestRect->top; + int IntPart = (((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * SourceGDI->SurfObj.lDelta) / 4; //((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * (SourceRect->right - SourceRect->left); + int FractPart = (SourceRect->bottom - SourceRect->top) % (DestRect->bottom - DestRect->top); + int Mid = (DestRect->bottom - DestRect->top) >> 1; int E = 0; int skip; PIXEL *ScanLine, *ScanLineAhead; PIXEL *PrevSource = NULL; PIXEL *PrevSourceAhead = NULL; + PIXEL *Target = (PIXEL *) (DestGDI->SurfObj.pvScan0 + (DestRect->top * DestGDI->SurfObj.lDelta) + 4 * DestRect->left); + PIXEL *Source = (PIXEL *) (SourceGDI->SurfObj.pvScan0 + (SourceRect->top * SourceGDI->SurfObj.lDelta) + 4 * SourceRect->left); + PSPAN ClipSpans; + UINT ClipSpansCount; + UINT SpanIndex; + LONG DestY; - skip = (TgtHeight < SrcHeight) ? 0 : (TgtHeight / (2*SrcHeight) + 1); + if (! ClipobjToSpans(&ClipSpans, &ClipSpansCount, ClipRegion, DestRect)) + { + return FALSE; + } + if (0 == ClipSpansCount) + { + /* No clip spans == empty clipping region, everything clipped away */ + ASSERT(NULL == ClipSpans); + return TRUE; + } + skip = (DestRect->bottom - DestRect->top < SourceRect->bottom - SourceRect->top) ? 0 : ((DestRect->bottom - DestRect->top) / (2 * (SourceRect->bottom - SourceRect->top)) + 1); NumPixels -= skip; - ScanLine = (PIXEL*)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); // FIXME: Should we use PagedPool here? - ScanLineAhead = (PIXEL *)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); + ScanLine = (PIXEL*)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL)); + ScanLineAhead = (PIXEL *)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL)); + DestY = DestRect->top; + SpanIndex = 0; while (NumPixels-- > 0) { if (Source != PrevSource) { if (Source == PrevSourceAhead) { @@ -469,38 +527,57 @@ void ScaleRectAvg32(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight, ScanLine = ScanLineAhead; ScanLineAhead = tmp; } else { - ScaleLineAvg32(ScanLine, Source, SrcWidth, TgtWidth); + ScaleLineAvg32(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left); } /* if */ PrevSource = Source; } /* if */ - if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + srcPitch)) { + if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta)) { int x; - ScaleLineAvg32(ScanLineAhead, (PIXEL *)((BYTE *)Source + srcPitch), SrcWidth, TgtWidth); - for (x = 0; x < TgtWidth; x++) + ScaleLineAvg32(ScanLineAhead, (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta), SourceRect->right - SourceRect->left, DestRect->right - DestRect->left); + for (x = 0; x < DestRect->right - DestRect->left; x++) ScanLine[x] = average32(ScanLine[x], ScanLineAhead[x]); - PrevSourceAhead = (PIXEL *)((BYTE *)Source + srcPitch); + PrevSourceAhead = (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta); } /* if */ - memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); - Target = (PIXEL *)((BYTE *)Target + dstPitch); + if (! FinalCopy32(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect)) + { + /* No more spans, everything else is clipped away, we're done */ + ExFreePool(ClipSpans); + ExFreePool(ScanLine); + ExFreePool(ScanLineAhead); + return TRUE; + } + DestY++; + Target = (PIXEL *)((BYTE *)Target + DestGDI->SurfObj.lDelta); Source += IntPart; E += FractPart; - if (E >= TgtHeight) { - E -= TgtHeight; - Source = (PIXEL *)((BYTE *)Source + srcPitch); + if (E >= DestRect->bottom - DestRect->top) { + E -= DestRect->bottom - DestRect->top; + Source = (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta); } /* if */ } /* while */ if (skip > 0 && Source != PrevSource) - ScaleLineAvg32(ScanLine, Source, SrcWidth, TgtWidth); + ScaleLineAvg32(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left); while (skip-- > 0) { - memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); - Target = (PIXEL *)((BYTE *)Target + dstPitch); + if (! FinalCopy32(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect)) + { + /* No more spans, everything else is clipped away, we're done */ + ExFreePool(ClipSpans); + ExFreePool(ScanLine); + ExFreePool(ScanLineAhead); + return TRUE; + } + DestY++; + Target = (PIXEL *)((BYTE *)Target + DestGDI->SurfObj.lDelta); } /* while */ + ExFreePool(ClipSpans); ExFreePool(ScanLine); ExFreePool(ScanLineAhead); + + return TRUE; } //NOTE: If you change something here, please do the same in other dibXXbpp.c files! @@ -508,11 +585,10 @@ BOOLEAN DIB_32BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrigin, - XLATEOBJ *ColorTranslation, ULONG Mode) + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode) { - BYTE *SourceLine, *DestLine; - - DbgPrint("DIB_32BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n", + DPRINT("DIB_32BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n", SourceGDI->BitsPerPixel, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); @@ -539,15 +615,12 @@ BOOLEAN DIB_32BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, break; case 32: - SourceLine = SourceSurf->pvScan0 + (SourceRect->top * SourceSurf->lDelta) + 4 * SourceRect->left; - DestLine = DestSurf->pvScan0 + (DestRect->top * DestSurf->lDelta) + 4 * DestRect->left; - ScaleRectAvg32((PIXEL *)DestLine, (PIXEL *)SourceLine, - SourceRect->right-SourceRect->left, SourceRect->bottom-SourceRect->top, - DestRect->right-DestRect->left, DestRect->bottom-DestRect->top, SourceSurf->lDelta, DestSurf->lDelta); + return ScaleRectAvg32(DestGDI, SourceGDI, DestRect, SourceRect, MaskOrigin, BrushOrigin, + ClipRegion, ColorTranslation, Mode); break; default: - //DbgPrint("DIB_32BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); + //DPRINT1("DIB_32BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); return FALSE; } diff --git a/reactos/subsys/win32k/dib/dib4bpp.c b/reactos/subsys/win32k/dib/dib4bpp.c index 7fc52aa891e..37730023f61 100644 --- a/reactos/subsys/win32k/dib/dib4bpp.c +++ b/reactos/subsys/win32k/dib/dib4bpp.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dib4bpp.c,v 1.34 2004/05/10 17:07:17 weiden Exp $ */ +/* $Id: dib4bpp.c,v 1.35 2004/05/14 22:56:17 gvg Exp $ */ #include VOID @@ -390,7 +390,8 @@ BOOLEAN DIB_4BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrigin, - XLATEOBJ *ColorTranslation, ULONG Mode) + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode) { DbgPrint("DIB_4BPP_StretchBlt: Source BPP: %u\n", SourceGDI->BitsPerPixel); return FALSE; diff --git a/reactos/subsys/win32k/dib/dib8bpp.c b/reactos/subsys/win32k/dib/dib8bpp.c index ce217be3ec9..6b7a6e5e76b 100644 --- a/reactos/subsys/win32k/dib/dib8bpp.c +++ b/reactos/subsys/win32k/dib/dib8bpp.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dib8bpp.c,v 1.25 2004/05/10 17:07:17 weiden Exp $ */ +/* $Id: dib8bpp.c,v 1.26 2004/05/14 22:56:17 gvg Exp $ */ #include VOID @@ -252,7 +252,7 @@ DIB_8BPP_BitBltSrcCopy(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, break; default: - DbgPrint("DIB_8BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); + DPRINT1("DIB_8BPP_Bitblt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); return FALSE; } @@ -432,26 +432,84 @@ void ScaleLineAvg8(PIXEL *Target, PIXEL *Source, int SrcWidth, int TgtWidth) *Target++ = *Source; } -//NOTE: If you change something here, please do the same in other dibXXbpp.c files! -void ScaleRectAvg8(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight, - int TgtWidth, int TgtHeight, int srcPitch, int dstPitch) +static BOOLEAN +FinalCopy8(PIXEL *Target, PIXEL *Source, PSPAN ClipSpans, UINT ClipSpansCount, UINT *SpanIndex, + UINT DestY, RECTL *DestRect) { - int NumPixels = TgtHeight; - int IntPart = ((SrcHeight / TgtHeight) * srcPitch); //(SrcHeight / TgtHeight) * SrcWidth; - int FractPart = SrcHeight % TgtHeight; - int Mid = TgtHeight >> 1; + LONG Left, Right; + + while (ClipSpans[*SpanIndex].Y < DestY + || (ClipSpans[*SpanIndex].Y == DestY + && ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width < DestRect->left)) + { + (*SpanIndex)++; + if (ClipSpansCount <= *SpanIndex) + { + /* No more spans, everything else is clipped away, we're done */ + return FALSE; + } + } + while (ClipSpans[*SpanIndex].Y == DestY) + { + if (ClipSpans[*SpanIndex].X < DestRect->right) + { + Left = max(ClipSpans[*SpanIndex].X, DestRect->left); + Right = min(ClipSpans[*SpanIndex].X + ClipSpans[*SpanIndex].Width, DestRect->right); + memcpy(Target + Left - DestRect->left, Source + Left - DestRect->left, + (Right - Left) * sizeof(PIXEL)); + } + (*SpanIndex)++; + if (ClipSpansCount <= *SpanIndex) + { + /* No more spans, everything else is clipped away, we're done */ + return FALSE; + } + } + + return TRUE; +} + +//NOTE: If you change something here, please do the same in other dibXXbpp.c files! +BOOLEAN ScaleRectAvg8(SURFGDI *DestGDI, SURFGDI *SourceGDI, + RECTL* DestRect, RECTL *SourceRect, + POINTL* MaskOrigin, POINTL BrushOrigin, + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode) +{ + int NumPixels = DestRect->bottom - DestRect->top; + int IntPart = (((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * SourceGDI->SurfObj.lDelta); //((SourceRect->bottom - SourceRect->top) / (DestRect->bottom - DestRect->top)) * (SourceRect->right - SourceRect->left); + int FractPart = (SourceRect->bottom - SourceRect->top) % (DestRect->bottom - DestRect->top); + int Mid = (DestRect->bottom - DestRect->top) >> 1; int E = 0; int skip; PIXEL *ScanLine, *ScanLineAhead; PIXEL *PrevSource = NULL; PIXEL *PrevSourceAhead = NULL; + PIXEL *Target = (PIXEL *) (DestGDI->SurfObj.pvScan0 + (DestRect->top * DestGDI->SurfObj.lDelta) + DestRect->left); + PIXEL *Source = (PIXEL *) (SourceGDI->SurfObj.pvScan0 + (SourceRect->top * SourceGDI->SurfObj.lDelta) + SourceRect->left); + PSPAN ClipSpans; + UINT ClipSpansCount; + UINT SpanIndex; + LONG DestY; - skip = (TgtHeight < SrcHeight) ? 0 : (TgtHeight / (2*SrcHeight) + 1); + if (! ClipobjToSpans(&ClipSpans, &ClipSpansCount, ClipRegion, DestRect)) + { + return FALSE; + } + if (0 == ClipSpansCount) + { + /* No clip spans == empty clipping region, everything clipped away */ + ASSERT(NULL == ClipSpans); + return TRUE; + } + skip = (DestRect->bottom - DestRect->top < SourceRect->bottom - SourceRect->top) ? 0 : ((DestRect->bottom - DestRect->top) / (2 * (SourceRect->bottom - SourceRect->top)) + 1); NumPixels -= skip; - ScanLine = (PIXEL*)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); // FIXME: Should we use PagedPool here? - ScanLineAhead = (PIXEL *)ExAllocatePool(NonPagedPool, TgtWidth*sizeof(PIXEL)); + ScanLine = (PIXEL*)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL)); + ScanLineAhead = (PIXEL *)ExAllocatePool(PagedPool, (DestRect->right - DestRect->left) * sizeof(PIXEL)); + DestY = DestRect->top; + SpanIndex = 0; while (NumPixels-- > 0) { if (Source != PrevSource) { if (Source == PrevSourceAhead) { @@ -463,49 +521,67 @@ void ScaleRectAvg8(PIXEL *Target, PIXEL *Source, int SrcWidth, int SrcHeight, ScanLine = ScanLineAhead; ScanLineAhead = tmp; } else { - ScaleLineAvg8(ScanLine, Source, SrcWidth, TgtWidth); + ScaleLineAvg8(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left); } /* if */ PrevSource = Source; } /* if */ - if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + srcPitch)) { + if (E >= Mid && PrevSourceAhead != (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta)) { int x; - ScaleLineAvg8(ScanLineAhead, (PIXEL *)((BYTE *)Source + srcPitch), SrcWidth, TgtWidth); - for (x = 0; x < TgtWidth; x++) + ScaleLineAvg8(ScanLineAhead, (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta), SourceRect->right - SourceRect->left, DestRect->right - DestRect->left); + for (x = 0; x < DestRect->right - DestRect->left; x++) ScanLine[x] = average8(ScanLine[x], ScanLineAhead[x]); - PrevSourceAhead = (PIXEL *)((BYTE *)Source + srcPitch); + PrevSourceAhead = (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta); } /* if */ - memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); - Target = (PIXEL *)((BYTE *)Target + dstPitch); + if (! FinalCopy8(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect)) + { + /* No more spans, everything else is clipped away, we're done */ + ExFreePool(ClipSpans); + ExFreePool(ScanLine); + ExFreePool(ScanLineAhead); + return TRUE; + } + DestY++; + Target = (PIXEL *)((BYTE *)Target + DestGDI->SurfObj.lDelta); Source += IntPart; E += FractPart; - if (E >= TgtHeight) { - E -= TgtHeight; - Source = (PIXEL *)((BYTE *)Source + srcPitch); + if (E >= DestRect->bottom - DestRect->top) { + E -= DestRect->bottom - DestRect->top; + Source = (PIXEL *)((BYTE *)Source + SourceGDI->SurfObj.lDelta); } /* if */ } /* while */ if (skip > 0 && Source != PrevSource) - ScaleLineAvg8(ScanLine, Source, SrcWidth, TgtWidth); + ScaleLineAvg8(ScanLine, Source, SourceRect->right - SourceRect->left, DestRect->right - DestRect->left); while (skip-- > 0) { - memcpy(Target, ScanLine, TgtWidth*sizeof(PIXEL)); - Target = (PIXEL *)((BYTE *)Target + dstPitch); + if (! FinalCopy8(Target, ScanLine, ClipSpans, ClipSpansCount, &SpanIndex, DestY, DestRect)) + { + /* No more spans, everything else is clipped away, we're done */ + ExFreePool(ClipSpans); + ExFreePool(ScanLine); + ExFreePool(ScanLineAhead); + return TRUE; + } + DestY++; + Target = (PIXEL *)((BYTE *)Target + DestGDI->SurfObj.lDelta); } /* while */ + ExFreePool(ClipSpans); ExFreePool(ScanLine); ExFreePool(ScanLineAhead); + + return TRUE; } BOOLEAN DIB_8BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrigin, - XLATEOBJ *ColorTranslation, ULONG Mode) + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode) { - BYTE *SourceLine, *DestLine; - - DbgPrint("DIB_8BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n", + DPRINT("DIB_8BPP_StretchBlt: Source BPP: %u, srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n", SourceGDI->BitsPerPixel, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom, DestRect->left, DestRect->top, DestRect->right, DestRect->bottom); @@ -520,12 +596,8 @@ BOOLEAN DIB_8BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, break; case 8: - SourceLine = SourceSurf->pvScan0 + (SourceRect->top * SourceSurf->lDelta) + SourceRect->left; - DestLine = DestSurf->pvScan0 + (DestRect->top * DestSurf->lDelta) + DestRect->left; - - ScaleRectAvg8((PIXEL *)DestLine, (PIXEL *)SourceLine, - SourceRect->right-SourceRect->left, SourceRect->bottom-SourceRect->top, - DestRect->right-DestRect->left, DestRect->bottom-DestRect->top, SourceSurf->lDelta, DestSurf->lDelta); + return ScaleRectAvg8(DestGDI, SourceGDI, DestRect, SourceRect, MaskOrigin, BrushOrigin, + ClipRegion, ColorTranslation, Mode); break; case 16: @@ -541,7 +613,7 @@ BOOLEAN DIB_8BPP_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, break; default: - DbgPrint("DIB_8BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); + DPRINT1("DIB_8BPP_StretchBlt: Unhandled Source BPP: %u\n", SourceGDI->BitsPerPixel); return FALSE; } diff --git a/reactos/subsys/win32k/eng/bitblt.c b/reactos/subsys/win32k/eng/bitblt.c index 5db8f9de343..9bd1592cfb5 100644 --- a/reactos/subsys/win32k/eng/bitblt.c +++ b/reactos/subsys/win32k/eng/bitblt.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: bitblt.c,v 1.54 2004/05/10 17:07:17 weiden Exp $ +/* $Id: bitblt.c,v 1.55 2004/05/14 22:56:18 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -45,6 +45,7 @@ typedef BOOLEAN STDCALL (*PSTRETCHRECTFUNC)(SURFOBJ* OutputObj, SURFOBJ* InputObj, SURFGDI* InputGDI, SURFOBJ* Mask, + CLIPOBJ* ClipRegion, XLATEOBJ* ColorTranslation, RECTL* OutputRect, RECTL* InputRect, @@ -593,6 +594,7 @@ CallDibStretchBlt(SURFOBJ* OutputObj, SURFOBJ* InputObj, SURFGDI* InputGDI, SURFOBJ* Mask, + CLIPOBJ* ClipRegion, XLATEOBJ* ColorTranslation, RECTL* OutputRect, RECTL* InputRect, @@ -609,7 +611,7 @@ CallDibStretchBlt(SURFOBJ* OutputObj, { RealBrushOrigin = *BrushOrigin; } - return OutputGDI->DIB_StretchBlt(OutputObj, InputObj, OutputGDI, InputGDI, OutputRect, InputRect, MaskOrigin, RealBrushOrigin, ColorTranslation, Mode); + return OutputGDI->DIB_StretchBlt(OutputObj, InputObj, OutputGDI, InputGDI, OutputRect, InputRect, MaskOrigin, RealBrushOrigin, ClipRegion, ColorTranslation, Mode); } @@ -631,10 +633,6 @@ EngStretchBlt( { // www.osr.com/ddk/graphics/gdifncs_0bs7.htm - BYTE clippingType; - RECTL CombinedRect; -// RECT_ENUM RectEnum; -// BOOL EnumMore; SURFGDI* OutputGDI; SURFGDI* InputGDI; POINTL InputPoint; @@ -645,30 +643,26 @@ EngStretchBlt( INTENG_ENTER_LEAVE EnterLeaveDest; SURFOBJ* InputObj; SURFOBJ* OutputObj; - PSTRETCHRECTFUNC BltRectFunc; + PSTRETCHRECTFUNC BltRectFunc; BOOLEAN Ret; - RECTL ClipRect; -// unsigned i; - POINTL Pt; -// ULONG Direction; - POINTL AdjustedBrushOrigin; + POINTL AdjustedBrushOrigin; - InputRect.left = prclSrc->left; - InputRect.right = prclSrc->right; - InputRect.top = prclSrc->top; - InputRect.bottom = prclSrc->bottom; + InputRect.left = prclSrc->left; + InputRect.right = prclSrc->right; + InputRect.top = prclSrc->top; + InputRect.bottom = prclSrc->bottom; if (! IntEngEnter(&EnterLeaveSource, SourceObj, &InputRect, TRUE, &Translate, &InputObj)) { - return FALSE; + return FALSE; } - InputPoint.x = InputRect.left + Translate.x; - InputPoint.y = InputRect.top + Translate.y; + InputPoint.x = InputRect.left + Translate.x; + InputPoint.y = InputRect.top + Translate.y; if (NULL != InputObj) { - InputGDI = (SURFGDI*) AccessInternalObjectFromUserObject(InputObj); + InputGDI = (SURFGDI*) AccessInternalObjectFromUserObject(InputObj); } else { @@ -676,44 +670,19 @@ EngStretchBlt( } OutputRect = *prclDest; - if (NULL != ClipRegion) - { - if (OutputRect.left < ClipRegion->rclBounds.left) - { - InputRect.left += ClipRegion->rclBounds.left - OutputRect.left; - InputPoint.x += ClipRegion->rclBounds.left - OutputRect.left; - OutputRect.left = ClipRegion->rclBounds.left; - } - if (ClipRegion->rclBounds.right < OutputRect.right) - { - InputRect.right -= OutputRect.right - ClipRegion->rclBounds.right; - OutputRect.right = ClipRegion->rclBounds.right; - } - if (OutputRect.top < ClipRegion->rclBounds.top) - { - InputRect.top += ClipRegion->rclBounds.top - OutputRect.top; - InputPoint.y += ClipRegion->rclBounds.top - OutputRect.top; - OutputRect.top = ClipRegion->rclBounds.top; - } - if (ClipRegion->rclBounds.bottom < OutputRect.bottom) - { - InputRect.bottom -= OutputRect.bottom - ClipRegion->rclBounds.bottom; - OutputRect.bottom = ClipRegion->rclBounds.bottom; - } - } /* Check for degenerate case: if height or width of OutputRect is 0 pixels there's nothing to do */ if (OutputRect.right <= OutputRect.left || OutputRect.bottom <= OutputRect.top) { - IntEngLeave(&EnterLeaveSource); - return TRUE; + IntEngLeave(&EnterLeaveSource); + return TRUE; } if (! IntEngEnter(&EnterLeaveDest, DestObj, &OutputRect, FALSE, &Translate, &OutputObj)) { - IntEngLeave(&EnterLeaveSource); - return FALSE; + IntEngLeave(&EnterLeaveSource); + return FALSE; } OutputRect.left = prclDest->left + Translate.x; @@ -721,28 +690,22 @@ EngStretchBlt( OutputRect.top = prclDest->top + Translate.y; OutputRect.bottom = prclDest->bottom + Translate.y; - if(BrushOrigin) - { - AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x; - AdjustedBrushOrigin.y = BrushOrigin->y + Translate.y; - } + if (NULL != BrushOrigin) + { + AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x; + AdjustedBrushOrigin.y = BrushOrigin->y + Translate.y; + } else - AdjustedBrushOrigin = Translate; + { + AdjustedBrushOrigin = Translate; + } if (NULL != OutputObj) { - OutputGDI = (SURFGDI*)AccessInternalObjectFromUserObject(OutputObj); + OutputGDI = (SURFGDI*)AccessInternalObjectFromUserObject(OutputObj); } - // Determine clipping type - if (ClipRegion == (CLIPOBJ *) NULL) - { - clippingType = DC_TRIVIAL; - } else { - clippingType = ClipRegion->iDComplexity; - } - - if (Mask != NULL)//(0xaacc == Rop4) + if (Mask != NULL) { //BltRectFunc = BltMask; DPRINT("EngStretchBlt isn't capable of handling mask yet.\n"); @@ -757,70 +720,9 @@ EngStretchBlt( } - switch(clippingType) - { - case DC_TRIVIAL: - Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation, - &OutputRect, &InputRect, MaskOrigin, &AdjustedBrushOrigin, Mode); - break; - case DC_RECT: - // Clip the blt to the clip rectangle - ClipRect.left = ClipRegion->rclBounds.left + Translate.x; - ClipRect.right = ClipRegion->rclBounds.right + Translate.x; - ClipRect.top = ClipRegion->rclBounds.top + Translate.y; - ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y; - EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect); - Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left; - Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top; - Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation, - &OutputRect, &InputRect, MaskOrigin, &AdjustedBrushOrigin, Mode); - //Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation, - // &CombinedRect, &Pt, MaskOrigin, Brush, BrushOrigin, Rop4); - DPRINT("EngStretchBlt() doesn't support DC_RECT clipping yet, so blitting w/o clip.\n"); - break; - // TODO: Complex clipping - /* - case DC_COMPLEX: - Ret = TRUE; - if (OutputObj == InputObj) - { - if (OutputRect.top < InputPoint.y) - { - Direction = OutputRect.left < InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN; - } - else - { - Direction = OutputRect.left < InputPoint.x ? CD_RIGHTUP : CD_LEFTUP; - } - } - else - { - Direction = CD_ANY; - } - CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, Direction, 0); - do - { - EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); - - for (i = 0; i < RectEnum.c; i++) - { - ClipRect.left = RectEnum.arcl[i].left + Translate.x; - ClipRect.right = RectEnum.arcl[i].right + Translate.x; - ClipRect.top = RectEnum.arcl[i].top + Translate.y; - ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y; - EngIntersectRect(&CombinedRect, &OutputRect, &ClipRect); - Pt.x = InputPoint.x + CombinedRect.left - OutputRect.left; - Pt.y = InputPoint.y + CombinedRect.top - OutputRect.top; - Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ColorTranslation, - &CombinedRect, &Pt, MaskOrigin, Brush, &AdjustedBrushOrigin, Rop4) && - Ret; - } - } - while(EnumMore); - break; - */ - } - + Ret = (*BltRectFunc)(OutputObj, OutputGDI, InputObj, InputGDI, Mask, ClipRegion, + ColorTranslation, &OutputRect, &InputRect, MaskOrigin, + &AdjustedBrushOrigin, Mode); IntEngLeave(&EnterLeaveDest); IntEngLeave(&EnterLeaveSource); @@ -844,8 +746,6 @@ IntEngStretchBlt(SURFOBJ *DestObj, BOOLEAN ret; SURFGDI *DestGDI; SURFGDI *SourceGDI; - RECTL OutputRect; - RECTL InputRect; COLORADJUSTMENT ca; POINT MaskOrigin; @@ -854,43 +754,19 @@ IntEngStretchBlt(SURFOBJ *DestObj, MaskOrigin.x = pMaskOrigin->x; MaskOrigin.y = pMaskOrigin->y; } - if (NULL != SourceRect) - { - InputRect = *SourceRect; - } - - // FIXME: Clipping is taken from IntEngBitBlt w/o modifications! - - /* Clip against the bounds of the clipping region so we won't try to write - * outside the surface */ - if (NULL != ClipRegion) - { - if (! EngIntersectRect(&OutputRect, DestRect, &ClipRegion->rclBounds)) - { - return TRUE; - } - DPRINT("Clipping isn't handled in IntEngStretchBlt() correctly yet\n"); - //InputPoint.x += OutputRect.left - DestRect->left; - //InputPoint.y += OutputRect.top - DestRect->top; - } - else - { - OutputRect = *DestRect; - } - if (NULL != SourceObj) { SourceGDI = (SURFGDI*) AccessInternalObjectFromUserObject(SourceObj); - MouseSafetyOnDrawStart(SourceObj, SourceGDI, InputRect.left, InputRect.top, - (InputRect.left + abs(InputRect.right - InputRect.left)), - (InputRect.top + abs(InputRect.bottom - InputRect.top))); + MouseSafetyOnDrawStart(SourceObj, SourceGDI, SourceRect->left, SourceRect->top, + (SourceRect->left + abs(SourceRect->right - SourceRect->left)), + (SourceRect->top + abs(SourceRect->bottom - SourceRect->top))); } /* No success yet */ ret = FALSE; DestGDI = (SURFGDI*)AccessInternalObjectFromUserObject(DestObj); - MouseSafetyOnDrawStart(DestObj, DestGDI, OutputRect.left, OutputRect.top, - OutputRect.right, OutputRect.bottom); + MouseSafetyOnDrawStart(DestObj, DestGDI, DestRect->left, DestRect->top, + DestRect->right, DestRect->bottom); /* Prepare color adjustment */ @@ -902,7 +778,7 @@ IntEngStretchBlt(SURFOBJ *DestObj, // FIXME: MaskOrigin is always NULL ! IntLockGDIDriver(DestGDI); ret = DestGDI->StretchBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation, - &ca, BrushOrigin, &OutputRect, &InputRect, NULL, Mode); + &ca, BrushOrigin, DestRect, SourceRect, NULL, Mode); IntUnLockGDIDriver(DestGDI); } @@ -910,7 +786,7 @@ IntEngStretchBlt(SURFOBJ *DestObj, { // FIXME: see previous fixme ret = EngStretchBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation, - &ca, BrushOrigin, &OutputRect, &InputRect, NULL, Mode); + &ca, BrushOrigin, DestRect, SourceRect, NULL, Mode); } MouseSafetyOnDrawEnd(DestObj, DestGDI); diff --git a/reactos/subsys/win32k/eng/clip.c b/reactos/subsys/win32k/eng/clip.c index 7aa2d0a9138..cd4dd17590c 100644 --- a/reactos/subsys/win32k/eng/clip.c +++ b/reactos/subsys/win32k/eng/clip.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: clip.c,v 1.20 2004/05/10 17:07:17 weiden Exp $ +/* $Id: clip.c,v 1.21 2004/05/14 22:56:18 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -333,4 +333,123 @@ CLIPOBJ_bEnum(IN CLIPOBJ* ClipObj, return ClipGDI->EnumPos < ClipGDI->EnumRects.c; } +static int +CompareSpans(const PSPAN Span1, const PSPAN Span2) +{ + int Cmp; + + if (Span1->Y < Span2->Y) + { + Cmp = -1; + } + else if (Span2->Y < Span1->Y) + { + Cmp = +1; + } + else + { + if (Span1->X < Span2->X) + { + Cmp = -1; + } + else if (Span2->X < Span1->X) + { + Cmp = +1; + } + else + { + Cmp = 0; + } + } + + return Cmp; +} + +BOOLEAN FASTCALL +ClipobjToSpans(PSPAN *Spans, UINT *Count, CLIPOBJ *ClipRegion, PRECTL Boundary) +{ + BOOL EnumMore; + UINT i, NewCount; + RECT_ENUM RectEnum; + PSPAN NewSpans; + RECTL *Rect; + + ASSERT(Boundary->top <= Boundary->bottom && Boundary->left <= Boundary->right); + + *Spans = NULL; + if (NULL == ClipRegion || DC_TRIVIAL == ClipRegion->iDComplexity) + { + *Count = Boundary->bottom - Boundary->top; + if (0 != *Count) + { + *Spans = ExAllocatePoolWithTag(PagedPool, *Count * sizeof(SPAN), TAG_CLIP); + if (NULL == *Spans) + { + *Count = 0; + return FALSE; + } + for (i = 0; i < Boundary->bottom - Boundary->top; i++) + { + (*Spans)[i].X = Boundary->left; + (*Spans)[i].Y = Boundary->top + i; + (*Spans)[i].Width = Boundary->right - Boundary->left; + } + } + + return TRUE; + } + + *Count = 0; + CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0); + do + { + EnumMore = CLIPOBJ_bEnum(ClipRegion, (ULONG) sizeof(RECT_ENUM), (PVOID) &RectEnum); + + NewCount = *Count; + for (i = 0; i < RectEnum.c; i++) + { + NewCount += RectEnum.arcl[i].bottom - RectEnum.arcl[i].top; + } + if (NewCount != *Count) + { + NewSpans = ExAllocatePoolWithTag(PagedPool, NewCount * sizeof(SPAN), TAG_CLIP); + if (NULL == NewSpans) + { + if (NULL != *Spans) + { + ExFreePool(*Spans); + *Spans = NULL; + } + *Count = 0; + return FALSE; + } + if (0 != *Count) + { + RtlCopyMemory(NewSpans, *Spans, *Count * sizeof(SPAN)); + ExFreePool(*Spans); + } + *Spans = NewSpans; + } + for (Rect = RectEnum.arcl; Rect < RectEnum.arcl + RectEnum.c; Rect++) + { + for (i = 0; i < Rect->bottom - Rect->top; i++) + { + (*Spans)[*Count].X = Rect->left; + (*Spans)[*Count].Y = Rect->top + i; + (*Spans)[*Count].Width = Rect->right - Rect->left; + (*Count)++; + } + } + ASSERT(*Count == NewCount); + } + while (EnumMore); + + if (0 != *Count) + { + EngSort((PBYTE) *Spans, sizeof(SPAN), *Count, (SORTCOMP) CompareSpans); + } + + return TRUE; +} + /* EOF */ diff --git a/reactos/subsys/win32k/eng/clip.h b/reactos/subsys/win32k/eng/clip.h index 8a9f19e5f04..dc0d079c9fe 100644 --- a/reactos/subsys/win32k/eng/clip.h +++ b/reactos/subsys/win32k/eng/clip.h @@ -32,4 +32,13 @@ typedef struct _RECT_ENUM RECTL arcl[ENUM_RECT_LIMIT]; } RECT_ENUM; +typedef struct tagSPAN +{ + LONG Y; + LONG X; + ULONG Width; +} SPAN, *PSPAN; + +BOOLEAN FASTCALL ClipobjToSpans(PSPAN *Spans, UINT *Count, CLIPOBJ *ClipRegion, PRECTL Boundary); + #endif diff --git a/reactos/subsys/win32k/eng/surface.c b/reactos/subsys/win32k/eng/surface.c index acaa4dbfa8d..effa51ab38e 100644 --- a/reactos/subsys/win32k/eng/surface.c +++ b/reactos/subsys/win32k/eng/surface.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: surface.c,v 1.38 2004/05/10 17:07:17 weiden Exp $ +/* $Id: surface.c,v 1.39 2004/05/14 22:56:18 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -110,7 +110,8 @@ static BOOLEAN Dummy_StretchBlt(SURFOBJ *DestSurf, SURFOBJ *SourceSurf, SURFGDI *DestGDI, SURFGDI *SourceGDI, RECTL* DestRect, RECTL *SourceRect, POINTL* MaskOrigin, POINTL BrushOrign, - XLATEOBJ *ColorTranslation, ULONG Mode) + CLIPOBJ *ClipRegion, XLATEOBJ *ColorTranslation, + ULONG Mode) { return FALSE; } diff --git a/reactos/subsys/win32k/include/tags.h b/reactos/subsys/win32k/include/tags.h index 08b29101d13..9ce0a959d69 100644 --- a/reactos/subsys/win32k/include/tags.h +++ b/reactos/subsys/win32k/include/tags.h @@ -26,6 +26,7 @@ #define TAG_BEZIER TAG('B', 'E', 'Z', 'R') /* bezier */ #define TAG_BITMAP TAG('B', 'T', 'M', 'P') /* bitmap */ #define TAG_PATBLT TAG('P', 'B', 'L', 'T') /* patblt */ +#define TAG_CLIP TAG('C', 'L', 'I', 'P') /* clipping */ #define TAG_COORD TAG('C', 'O', 'R', 'D') /* coords */ #define TAG_DC TAG('D', 'C', 'D', 'C') /* dc */ #define TAG_GDIOBJ TAG('G', 'D', 'I', 'O') /* gdi obj */