Author: gschneider
Date: Sun Feb 8 08:25:33 2009
New Revision: 39483
URL:
http://svn.reactos.org/svn/reactos?rev=39483&view=rev
Log:
StretchBlt: +clipping -bugs
- Additional checks (coordinates switched, NOOP, degenerate, outside of valid region, ...)
and offset source rectangle in internal StretchBlt functions
- Fixes the StretchBlt problem in bug #3477, bug #3656 completely as well as bug #4089 and
some issues reported elsewhere (bug #3325 for example)
- Increment horizontal position even if outside of the clipping rect (Evgeny Boltik,
<BSTSoft AT narod DOT ru>)
- One small problem is left, one cookie for the person who reproduces it, two for the one
that fixes it ;-)
Modified:
trunk/reactos/subsystems/win32/win32k/dib/dibXXbpp.c
trunk/reactos/subsystems/win32/win32k/eng/bitblt.c
Modified: trunk/reactos/subsystems/win32/win32k/dib/dibXXbpp.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/di…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/dib/dibXXbpp.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/dib/dibXXbpp.c [iso-8859-1] Sun Feb 8 08:25:33
2009
@@ -160,13 +160,13 @@
fnDest_PutPixel(DestSurf, DesX, DesY, color);
- sx += SrcZoomXHight;
- sx_dec += SrcZoomXLow;
- if (sx_dec >= sx_max)
- {
- sx++;
- sx_dec -= sx_max;
- }
+ }
+ sx += SrcZoomXHight;
+ sx_dec += SrcZoomXLow;
+ if (sx_dec >= sx_max)
+ {
+ sx++;
+ sx_dec -= sx_max;
}
}
Modified: trunk/reactos/subsystems/win32/win32k/eng/bitblt.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/en…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/eng/bitblt.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/eng/bitblt.c [iso-8859-1] Sun Feb 8 08:25:33
2009
@@ -825,7 +825,6 @@
{
//
www.osr.com/ddk/graphics/gdifncs_0bs7.htm
- POINTL InputPoint;
RECTL InputRect;
RECTL OutputRect;
POINTL Translate;
@@ -838,23 +837,79 @@
POINTL AdjustedBrushOrigin;
BOOL UsesSource = ROP4_USES_SOURCE(Mode);
- InputRect.left = prclSrc->left;
- InputRect.right = prclSrc->right;
- InputRect.top = prclSrc->top;
- InputRect.bottom = prclSrc->bottom;
-
+ if (Mode == R4_NOOP)
+ {
+ /* Copy destination onto itself: nop */
+ return TRUE;
+ }
+
+ OutputRect = *prclDest;
+ if (OutputRect.right < OutputRect.left)
+ {
+ OutputRect.left = prclDest->right;
+ OutputRect.right = prclDest->left;
+ }
+ if (OutputRect.bottom < OutputRect.top)
+ {
+ OutputRect.left = prclDest->right;
+ OutputRect.right = prclDest->left;
+ }
+
+ InputRect = *prclSrc;
if (UsesSource)
{
- if (! IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE,
&Translate, &psoInput))
+ if (NULL == prclSrc)
{
return FALSE;
}
- }
-
- InputPoint.x = InputRect.left + Translate.x;
- InputPoint.y = InputRect.top + Translate.y;
-
- OutputRect = *prclDest;
+
+ /* Make sure we don't try to copy anything outside the valid source region
*/
+ if (InputRect.left < 0)
+ {
+ OutputRect.left -= InputRect.left;
+ InputRect.left = 0;
+ }
+ if (InputRect.top < 0)
+ {
+ OutputRect.top -= InputRect.top;
+ InputRect.top = 0;
+ }
+
+ if (! IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE,
+ &Translate, &psoInput))
+ {
+ return FALSE;
+ }
+
+ InputRect.left += Translate.x;
+ InputRect.right += Translate.x;
+ InputRect.top += Translate.y;
+ InputRect.bottom += Translate.y;
+ }
+
+ if (NULL != ClipRegion)
+ {
+ if (OutputRect.left < ClipRegion->rclBounds.left)
+ {
+ InputRect.left += 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;
+ 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 */
@@ -876,12 +931,12 @@
return FALSE;
}
- OutputRect.left = prclDest->left + Translate.x;
- OutputRect.right = prclDest->right + Translate.x;
- OutputRect.top = prclDest->top + Translate.y;
- OutputRect.bottom = prclDest->bottom + Translate.y;
-
- if (NULL != BrushOrigin)
+ OutputRect.left += Translate.x;
+ OutputRect.right += Translate.x;
+ OutputRect.top += Translate.y;
+ OutputRect.bottom += Translate.y;
+
+ if (BrushOrigin)
{
AdjustedBrushOrigin.x = BrushOrigin->x + Translate.x;
AdjustedBrushOrigin.y = BrushOrigin->y + Translate.y;
@@ -906,7 +961,6 @@
{
BltRectFunc = CallDibStretchBlt;
}
-
Ret = (*BltRectFunc)(psoOutput, psoInput, Mask, ClipRegion,
ColorTranslation, &OutputRect, &InputRect, MaskOrigin,
@@ -939,12 +993,80 @@
POINT MaskOrigin;
SURFACE *psurfDest;
SURFACE *psurfSource = NULL;
+ RECTL InputClippedRect;
+ RECTL InputRect;
+ RECTL OutputRect;
BOOL UsesSource = ROP4_USES_SOURCE(ROP);
+ LONG InputClWidth, InputClHeight, InputWidth, InputHeight;
ASSERT(psoDest);
psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
ASSERT(psurfDest);
-
+ ASSERT(DestRect);
+
+ InputClippedRect = *DestRect;
+ if (InputClippedRect.right < InputClippedRect.left)
+ {
+ InputClippedRect.left = DestRect->right;
+ InputClippedRect.right = DestRect->left;
+ }
+ if (InputClippedRect.bottom < InputClippedRect.top)
+ {
+ InputClippedRect.top = DestRect->bottom;
+ InputClippedRect.bottom = DestRect->top;
+ }
+
+ if (UsesSource)
+ {
+ if (NULL == SourceRect || NULL == psoSource)
+ {
+ return FALSE;
+ }
+ InputRect = *SourceRect;
+
+ /* Make sure we don't try to copy anything outside the valid source region
*/
+ if (InputRect.left < 0)
+ {
+ InputClippedRect.left -= InputRect.left;
+ InputRect.left = 0;
+ }
+ if (InputRect.top < 0)
+ {
+ InputClippedRect.top -= InputRect.top;
+ InputRect.top = 0;
+ }
+
+ if (InputClippedRect.right < InputClippedRect.left ||
+ InputClippedRect.bottom < InputClippedRect.top)
+ {
+ /* Everything clipped away, nothing to do */
+ return TRUE;
+ }
+ }
+
+ if (ClipRegion)
+ {
+ if (! EngIntersectRect(&OutputRect, &InputClippedRect,
+ &ClipRegion->rclBounds))
+ {
+ return TRUE;
+ }
+ /* Update source rect */
+ InputClWidth = InputClippedRect.right - InputClippedRect.left;
+ InputClHeight = InputClippedRect.bottom - InputClippedRect.top;
+ InputWidth = InputRect.right - InputRect.left;
+ InputHeight = InputRect.bottom - InputRect.top;
+
+ InputRect.left += (InputWidth * (OutputRect.left - InputClippedRect.left)) /
InputClWidth;
+ InputRect.right -= (InputWidth * (InputClippedRect.right - OutputRect.right)) /
InputClWidth;
+ InputRect.top += (InputHeight * (OutputRect.top - InputClippedRect.top)) /
InputClHeight;
+ InputRect.bottom -= (InputHeight * (InputClippedRect.bottom - OutputRect.bottom))
/ InputClHeight;
+ }
+ else
+ {
+ OutputRect = InputClippedRect;
+ }
+
if (pMaskOrigin != NULL)
{
MaskOrigin.x = pMaskOrigin->x; MaskOrigin.y = pMaskOrigin->y;
@@ -952,21 +1074,19 @@
/* No success yet */
ret = FALSE;
- ASSERT(DestRect);
SURFACE_LockBitmapBits(psurfDest);
- MouseSafetyOnDrawStart(psoDest, DestRect->left, DestRect->top,
- DestRect->right, DestRect->bottom);
+ MouseSafetyOnDrawStart(psoDest, OutputRect.left, OutputRect.top,
+ OutputRect.right, OutputRect.bottom);
if (UsesSource)
{
psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
- ASSERT(SourceRect);
if (psoSource != psoDest)
{
SURFACE_LockBitmapBits(psurfSource);
}
- MouseSafetyOnDrawStart(psoSource, SourceRect->left, SourceRect->top,
- SourceRect->right, SourceRect->bottom);
+ MouseSafetyOnDrawStart(psoSource, InputRect.left, InputRect.top,
+ InputRect.right, InputRect.bottom);
}
/* Prepare color adjustment */
@@ -978,14 +1098,14 @@
// FIXME: MaskOrigin is always NULL !
ret = GDIDEVFUNCS(psoDest).StretchBlt(
psoDest, (UsesSource) ? psoSource : NULL, MaskSurf, ClipRegion,
ColorTranslation,
- &ca, BrushOrigin, DestRect, SourceRect, NULL, ROP);
+ &ca, BrushOrigin, &OutputRect, &InputRect, NULL, ROP);
}
if (! ret)
{
// FIXME: see previous fixme
ret = EngStretchBlt(psoDest, psoSource, MaskSurf, ClipRegion, ColorTranslation,
- &ca, BrushOrigin, DestRect, SourceRect, NULL, ROP);
+ &ca, BrushOrigin, &OutputRect, &InputRect, NULL,
ROP);
}
if (UsesSource)