[YAROTOWS] Reintegrate the branch. For a brighter future.
[reactos.git] / reactos / subsystems / win32 / win32k / eng / transblt.c
index d06fecb..0bfc145 100644 (file)
@@ -12,9 +12,9 @@
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 /* $Id$
  *
  *        4/6/2004: Created
  */
 
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
 
-BOOL STDCALL
-EngTransparentBlt(SURFOBJ *Dest,
-                 SURFOBJ *Source,
+BOOL APIENTRY
+EngTransparentBlt(SURFOBJ *psoDest,
+                 SURFOBJ *psoSource,
                  CLIPOBJ *Clip,
                  XLATEOBJ *ColorTranslation,
                  PRECTL DestRect,
@@ -47,28 +47,41 @@ EngTransparentBlt(SURFOBJ *Dest,
   INTENG_ENTER_LEAVE EnterLeaveSource, EnterLeaveDest;
   SURFOBJ *InputObj, *OutputObj;
   RECTL OutputRect, InputRect;
-  POINTL Translate, InputPoint;
+  POINTL Translate;
 
-  InputRect.left = 0;
-  InputRect.right = DestRect->right - DestRect->left;
-  InputRect.top = 0;
-  InputRect.bottom = DestRect->bottom - DestRect->top;
+  LONG DstHeight;
+  LONG DstWidth;
+  LONG SrcHeight;
+  LONG SrcWidth;
 
-  if(!IntEngEnter(&EnterLeaveSource, Source, &InputRect, TRUE, &Translate, &InputObj))
+  InputRect = *SourceRect;
+
+  if(!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj))
   {
     return FALSE;
   }
-
-  InputPoint.x = SourceRect->left + Translate.x;
-  InputPoint.y = SourceRect->top + Translate.y;
+  InputRect.left += Translate.x;
+  InputRect.right += Translate.x;
+  InputRect.top += Translate.y;
+  InputRect.bottom += Translate.y;
 
   OutputRect = *DestRect;
+  if (OutputRect.right < OutputRect.left)
+  {
+    OutputRect.left = DestRect->right;
+    OutputRect.right = DestRect->left;
+  }
+  if (OutputRect.bottom < OutputRect.top)
+  {
+    OutputRect.top = DestRect->bottom;
+    OutputRect.bottom = DestRect->top;
+  }
+
   if(Clip)
   {
     if(OutputRect.left < Clip->rclBounds.left)
     {
       InputRect.left += Clip->rclBounds.left - OutputRect.left;
-      InputPoint.x += Clip->rclBounds.left - OutputRect.left;
       OutputRect.left = Clip->rclBounds.left;
     }
     if(Clip->rclBounds.right < OutputRect.right)
@@ -79,7 +92,6 @@ EngTransparentBlt(SURFOBJ *Dest,
     if(OutputRect.top < Clip->rclBounds.top)
     {
       InputRect.top += Clip->rclBounds.top - OutputRect.top;
-      InputPoint.y += Clip->rclBounds.top - OutputRect.top;
       OutputRect.top = Clip->rclBounds.top;
     }
     if(Clip->rclBounds.bottom < OutputRect.bottom)
@@ -97,7 +109,7 @@ EngTransparentBlt(SURFOBJ *Dest,
     return TRUE;
   }
 
-  if(!IntEngEnter(&EnterLeaveDest, Dest, &OutputRect, FALSE, &Translate, &OutputObj))
+  if(!IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &OutputObj))
   {
     IntEngLeave(&EnterLeaveSource);
     return FALSE;
@@ -110,28 +122,36 @@ EngTransparentBlt(SURFOBJ *Dest,
 
   ClippingType = (Clip ? Clip->iDComplexity : DC_TRIVIAL);
 
+  DstHeight = OutputRect.bottom - OutputRect.top;
+  DstWidth = OutputRect.right - OutputRect.left;
+  SrcHeight = InputRect.bottom - InputRect.top;
+  SrcWidth = InputRect.right - InputRect.left;
   switch(ClippingType)
   {
     case DC_TRIVIAL:
     {
-      Ret = DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_TransparentBlt(
-        OutputObj, InputObj, &OutputRect, &InputPoint, ColorTranslation, iTransColor);
+      Ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_TransparentBlt(
+        OutputObj, InputObj, &OutputRect, &InputRect, ColorTranslation, iTransColor);
       break;
     }
     case DC_RECT:
     {
       RECTL ClipRect, CombinedRect;
-      POINTL Pt;
+      RECTL InputToCombinedRect;
 
       ClipRect.left = Clip->rclBounds.left + Translate.x;
       ClipRect.right = Clip->rclBounds.right + Translate.x;
       ClipRect.top = Clip->rclBounds.top + Translate.y;
       ClipRect.bottom = Clip->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 = DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_TransparentBlt(
-        OutputObj, InputObj, &CombinedRect, &Pt, ColorTranslation, iTransColor);
+      if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
+      {
+        InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight;
+        InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
+        InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth;
+        InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth;
+        Ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_TransparentBlt(
+          OutputObj, InputObj, &CombinedRect, &InputToCombinedRect, ColorTranslation, iTransColor);
+      }
       break;
     }
     case DC_COMPLEX:
@@ -139,17 +159,16 @@ EngTransparentBlt(SURFOBJ *Dest,
       ULONG Direction, i;
       RECT_ENUM RectEnum;
       BOOL EnumMore;
-      POINTL Pt;
 
       if(OutputObj == InputObj)
       {
-        if(OutputRect.top < InputPoint.y)
+        if(OutputRect.top < InputRect.top)
         {
-          Direction = OutputRect.left < (InputPoint.x ? CD_RIGHTDOWN : CD_LEFTDOWN);
+          Direction = OutputRect.left < (InputRect.left ? CD_RIGHTDOWN : CD_LEFTDOWN);
         }
         else
         {
-          Direction = OutputRect.left < (InputPoint.x ? CD_RIGHTUP : CD_LEFTUP);
+          Direction = OutputRect.left < (InputRect.left ? CD_RIGHTUP : CD_LEFTUP);
         }
       }
       else
@@ -164,19 +183,25 @@ EngTransparentBlt(SURFOBJ *Dest,
         for (i = 0; i < RectEnum.c; i++)
         {
           RECTL ClipRect, CombinedRect;
+          RECTL InputToCombinedRect;
 
           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 = DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_TransparentBlt(
-            OutputObj, InputObj, &CombinedRect, &Pt, ColorTranslation, iTransColor);
-          if(!Ret)
+          if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect))
           {
-            break;
+            InputToCombinedRect.top = InputRect.top + (CombinedRect.top - OutputRect.top) * SrcHeight / DstHeight;
+            InputToCombinedRect.bottom = InputRect.top + (CombinedRect.bottom - OutputRect.top) * SrcHeight / DstHeight;
+            InputToCombinedRect.left = InputRect.left + (CombinedRect.left - OutputRect.left) * SrcWidth / DstWidth;
+            InputToCombinedRect.right = InputRect.left + (CombinedRect.right - OutputRect.left) * SrcWidth / DstWidth;
+
+            Ret = DibFunctionsForBitmapFormat[psoDest->iBitmapFormat].DIB_TransparentBlt(
+              OutputObj, InputObj, &CombinedRect, &InputToCombinedRect, ColorTranslation, iTransColor);
+            if(!Ret)
+            {
+              break;
+            }
           }
         }
       } while(EnumMore && Ret);
@@ -196,8 +221,8 @@ EngTransparentBlt(SURFOBJ *Dest,
 }
 
 BOOL FASTCALL
-IntEngTransparentBlt(SURFOBJ *DestSurf,
-                     SURFOBJ *SourceSurf,
+IntEngTransparentBlt(SURFOBJ *psoDest,
+                     SURFOBJ *psoSource,
                      CLIPOBJ *Clip,
                      XLATEOBJ *ColorTranslation,
                      PRECTL DestRect,
@@ -207,18 +232,20 @@ IntEngTransparentBlt(SURFOBJ *DestSurf,
 {
   BOOL Ret;
   RECTL OutputRect, InputClippedRect;
-  BITMAPOBJ *DestObj;
-  BITMAPOBJ *SourceObj;
+  SURFACE *psurfDest;
+  SURFACE *psurfSource;
+  RECTL InputRect;
+  LONG InputClWidth, InputClHeight, InputWidth, InputHeight;
 
-  ASSERT(DestSurf);
-  ASSERT(SourceSurf);
+  ASSERT(psoDest);
+  ASSERT(psoSource);
   ASSERT(DestRect);
 
-  DestObj = CONTAINING_RECORD(DestSurf, BITMAPOBJ, SurfObj);
-  SourceObj = CONTAINING_RECORD(SourceSurf, BITMAPOBJ, SurfObj);
+  psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
+  psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
 
-  ASSERT(DestObj);
-  ASSERT(SourceObj);
+  ASSERT(psurfDest);
+  ASSERT(psurfSource);
 
   InputClippedRect = *DestRect;
   if(InputClippedRect.right < InputClippedRect.left)
@@ -232,55 +259,44 @@ IntEngTransparentBlt(SURFOBJ *DestSurf,
     InputClippedRect.bottom = DestRect->top;
   }
 
+  InputRect = *SourceRect;
   /* Clip against the bounds of the clipping region so we won't try to write
    * outside the surface */
   if(Clip)
   {
-    if(!EngIntersectRect(&OutputRect, &InputClippedRect, &Clip->rclBounds))
+    if(!RECTL_bIntersectRect(&OutputRect, &InputClippedRect, &Clip->rclBounds))
     {
       return TRUE;
     }
-    SourceRect->left += OutputRect.left - DestRect->left;
-    SourceRect->top += OutputRect.top - DestRect->top;
-    SourceRect->right += OutputRect.left - DestRect->left;
-    SourceRect->bottom += OutputRect.top - DestRect->top;
+    /* 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 = *DestRect;
-  }
-
-  if(SourceSurf != DestSurf)
-  {
-    BITMAPOBJ_LockBitmapBits(SourceObj);
-    MouseSafetyOnDrawStart(SourceSurf, SourceRect->left, SourceRect->top,
-                           SourceRect->right, SourceRect->bottom);
+    OutputRect = InputClippedRect;
   }
-  BITMAPOBJ_LockBitmapBits(DestObj);
-  MouseSafetyOnDrawStart(DestSurf, OutputRect.left, OutputRect.top,
-                         OutputRect.right, OutputRect.bottom);
 
-  if(DestObj->flHooks & HOOK_TRANSPARENTBLT)
+  if(psurfDest->flags & HOOK_TRANSPARENTBLT)
   {
-    Ret = GDIDEVFUNCS(DestSurf).TransparentBlt(
-      DestSurf, SourceSurf, Clip, ColorTranslation, &OutputRect,
-      SourceRect, iTransColor, Reserved);
+    Ret = GDIDEVFUNCS(psoDest).TransparentBlt(
+      psoDest, psoSource, Clip, ColorTranslation, &OutputRect,
+      &InputRect, iTransColor, Reserved);
   }
   else
     Ret = FALSE;
 
   if(!Ret)
   {
-    Ret = EngTransparentBlt(DestSurf, SourceSurf, Clip, ColorTranslation,
-                            &OutputRect, SourceRect, iTransColor, Reserved);
-  }
-
-  MouseSafetyOnDrawEnd(DestSurf);
-  BITMAPOBJ_UnlockBitmapBits(DestObj);
-  if(SourceSurf != DestSurf)
-  {
-    MouseSafetyOnDrawEnd(SourceSurf);
-    BITMAPOBJ_UnlockBitmapBits(SourceObj);
+    Ret = EngTransparentBlt(psoDest, psoSource, Clip, ColorTranslation,
+                            &OutputRect, &InputRect, iTransColor, Reserved);
   }
 
   return Ret;