[WIN32SS][NTGDI][GDI32] Fix DPtoLP and NtGdiTransformPoints etc. (#1540)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Mon, 29 Apr 2019 05:45:44 +0000 (14:45 +0900)
committerGitHub <noreply@github.com>
Mon, 29 Apr 2019 05:45:44 +0000 (14:45 +0900)
Fix NtGdiTransformPoints, gdi32!DPtoLP, gdi32!LPtoDP and gdi32!SetMapMode functions. Fix CORE-15983. CORE-15983

win32ss/gdi/gdi32/objects/coord.c
win32ss/gdi/ntgdi/coord.c
win32ss/gdi/ntgdi/coord.h
win32ss/gdi/ntgdi/xformobj.c
win32ss/gdi/ntgdi/xformobj.h

index dd74b33..a42fa12 100644 (file)
@@ -171,28 +171,35 @@ DPtoLP(
     _Inout_updates_(nCount) LPPOINT lpPoints,
     _In_ INT nCount)
 {
-#if 0
-    INT i;
     PDC_ATTR pdcattr;
+    SIZEL sizlView;
 
-    /* Get the DC attribute */
-    pdcattr = GdiGetDcAttr(hdc);
-    if (!pdcattr)
+    if (nCount <= 0)
+        return TRUE;
+
+    if (hdc == NULL)
     {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
-
-    if (pdcattr->flXform & ANY_XFORM_CHANGES)
+    if (lpPoints == NULL)
     {
-        GdiFixupTransforms(pdcattr);
+        return TRUE;
     }
 
-    // FIXME: can this fail on Windows?
-    GdiTransformPoints(&pdcattr->mxDeviceToWorld, lpPoints, lpPoints, nCount);
+    pdcattr = GdiGetDcAttr(hdc);
+    if (pdcattr == NULL)
+        return FALSE;
+
+    if (pdcattr->iMapMode == MM_ISOTROPIC)
+    {
+        if (NtGdiGetDCPoint(hdc, GdiGetViewPortExt, (PPOINTL)&sizlView))
+        {
+            if (sizlView.cx == 0 || sizlView.cy == 0)
+                return FALSE;
+        }
+    }
 
-    return TRUE;
-#endif
     return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiDpToLp);
 }
 
@@ -203,28 +210,25 @@ LPtoDP(
     _Inout_updates_(nCount) LPPOINT lpPoints,
     _In_ INT nCount)
 {
-#if 0
-    INT i;
     PDC_ATTR pdcattr;
 
-    /* Get the DC attribute */
-    pdcattr = GdiGetDcAttr(hdc);
-    if (!pdcattr)
+    if (nCount <= 0)
+        return TRUE;
+
+    if (hdc == NULL)
     {
         SetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
-
-    if (pdcattr->flXform & ANY_XFORM_CHANGES)
+    if (lpPoints == NULL)
     {
-        GdiFixupTransforms(pdcattr);
+        return TRUE;
     }
 
-    // FIXME: can this fail on Windows?
-    GdiTransformPoints(&pdcattr->mxWorldToDevice, lpPoints, lpPoints, nCount);
+    pdcattr = GdiGetDcAttr(hdc);
+    if (pdcattr == NULL)
+        return FALSE;
 
-    return TRUE;
-#endif
     return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiLpToDp);
 }
 
@@ -490,6 +494,9 @@ SetViewportExtEx(
         (pdcattr->szlViewportExt.cy == nYExtent))
         return TRUE;
 
+    if (nXExtent == 0 || nYExtent == 0)
+        return TRUE;
+
     /* Only change viewport extension if we are in iso or aniso mode */
     if ((pdcattr->iMapMode == MM_ISOTROPIC) ||
         (pdcattr->iMapMode == MM_ANISOTROPIC))
@@ -512,7 +519,8 @@ SetViewportExtEx(
             NtGdiMirrorWindowOrg(hdc);
 
         /* Update xform flags */
-        pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
+        pdcattr->flXform |= (PAGE_EXTENTS_CHANGED | INVALIDATE_ATTRIBUTES |
+                             DEVICE_TO_WORLD_INVALID);
     }
 
     return TRUE;
index 58d2365..adaee5f 100644 (file)
@@ -3,7 +3,8 @@
  * PROJECT:          ReactOS kernel
  * PURPOSE:          Coordinate systems
  * FILE:             win32ss/gdi/ntgdi/coord.c
- * PROGRAMER:        Timo Kreuzer (timo.kreuzer@rectos.org)
+ * PROGRAMERS:       Timo Kreuzer (timo.kreuzer@rectos.org)
+ *                   Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
  */
 
 /* Coordinate translation overview
@@ -195,7 +196,7 @@ DC_vUpdateWorldToDevice(PDC pdc)
     XFORMOBJ_iCombine(&xoWorldToDevice, &xoWorldToPage, &xoPageToDevice);
 
     /* Reset the flags */
-    pdc->pdcattr->flXform &= ~(PAGE_XLATE_CHANGED|PAGE_EXTENTS_CHANGED|WORLD_XFORM_CHANGED);
+    pdc->pdcattr->flXform &= ~WORLD_XFORM_CHANGED;
 }
 
 VOID
@@ -213,7 +214,7 @@ DC_vUpdateDeviceToWorld(PDC pdc)
     XFORMOBJ_vInit(&xoDeviceToWorld, &pdc->pdcattr->mxDeviceToWorld);
     if (XFORMOBJ_iInverse(&xoDeviceToWorld, &xoWorldToDevice) == DDI_ERROR)
     {
-        // FIXME: do we need to reset anything?
+        MX_Set0(&pdc->pdcattr->mxDeviceToWorld);
         return;
     }
 
@@ -377,10 +378,14 @@ NtGdiTransformPoints(
     if (Count <= 0)
         return TRUE;
 
+    if (!UnsafePtsIn || !UnsafePtOut)
+    {
+        return FALSE;
+    }
+
     pdc = DC_LockDc(hDC);
     if (!pdc)
     {
-        EngSetLastError(ERROR_INVALID_PARAMETER);
         return FALSE;
     }
 
@@ -595,7 +600,7 @@ NtGdiOffsetViewportOrgEx(
     }
     pdcattr->ptlViewportOrg.x += XOffset;
     pdcattr->ptlViewportOrg.y += YOffset;
-    pdcattr->flXform |= PAGE_XLATE_CHANGED;
+    pdcattr->flXform |= PAGE_XLATE_CHANGED | DEVICE_TO_WORLD_INVALID;
 
     DC_UnlockDc(dc);
 
@@ -821,6 +826,9 @@ IntGdiSetMapMode(
     FLONG flXform;
     PDC_ATTR pdcattr = dc->pdcattr;
 
+    if (MapMode == pdcattr->iMapMode)
+        return MapMode;
+
     flXform = pdcattr->flXform & ~(ISO_OR_ANISO_MAP_MODE|PTOD_EFM22_NEGATIVE|
         PTOD_EFM11_NEGATIVE|POSITIVE_Y_IS_UP|PAGE_TO_DEVICE_SCALE_IDENTITY|
         PAGE_TO_DEVICE_IDENTITY);
@@ -921,7 +929,7 @@ GreSetViewportOrgEx(
 
     pdcattr->ptlViewportOrg.x = X;
     pdcattr->ptlViewportOrg.y = Y;
-    pdcattr->flXform |= PAGE_XLATE_CHANGED;
+    pdcattr->flXform |= PAGE_XLATE_CHANGED | DEVICE_TO_WORLD_INVALID;
 
     DC_UnlockDc(dc);
     return TRUE;
@@ -972,7 +980,7 @@ NtGdiSetViewportOrgEx(
 
     pdcattr->ptlViewportOrg.x = X;
     pdcattr->ptlViewportOrg.y = Y;
-    pdcattr->flXform |= PAGE_XLATE_CHANGED;
+    pdcattr->flXform |= PAGE_XLATE_CHANGED | DEVICE_TO_WORLD_INVALID;
 
     DC_UnlockDc(dc);
 
@@ -1024,7 +1032,7 @@ NtGdiSetWindowOrgEx(
 
     pdcattr->ptlWindowOrg.x = X;
     pdcattr->ptlWindowOrg.y = Y;
-    pdcattr->flXform |= PAGE_XLATE_CHANGED;
+    pdcattr->flXform |= PAGE_XLATE_CHANGED | DEVICE_TO_WORLD_INVALID;
 
     DC_UnlockDc(dc);
 
@@ -1060,7 +1068,7 @@ IntMirrorWindowOrg(PDC dc)
     X = (X * pdcattr->szlWindowExt.cx) / cx;
 
     pdcattr->ptlWindowOrg.x = pdcattr->lWindowOrgx - X; // Now set the inverted win origion.
-    pdcattr->flXform |= PAGE_XLATE_CHANGED;
+    pdcattr->flXform |= PAGE_XLATE_CHANGED | DEVICE_TO_WORLD_INVALID;
 
     return;
 }
index dc3228d..9c7a75b 100644 (file)
@@ -131,6 +131,9 @@ DC_vXformDeviceToWorld(
     PMATRIX pmx;
 
     pmx = DC_pmxDeviceToWorld(pdc);
+    if (!MX_IsInvertible(pmx))
+        return;
+
     XFORMOBJ_vInit(&xo, pmx);
     XFORMOBJ_bApplyXform(&xo, XF_LTOL, cNumPoints, pptlDest, pptlSource);
 }
index e1d2241..02216a5 100644 (file)
@@ -3,7 +3,8 @@
  * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            win32ss/gdi/ntgdi/xformobj.c
  * PURPOSE:         XFORMOBJ API
- * PROGRAMMER:      Timo Kreuzer
+ * PROGRAMMERS:     Timo Kreuzer
+ *                  Katayama Hirofumi MZ
  */
 
 /** Includes ******************************************************************/
@@ -243,6 +244,25 @@ XFORMOBJ_iCombineXform(
     }
 }
 
+BOOL FASTCALL
+MX_IsInvertible(IN PMATRIX pmx)
+{
+    FLOATOBJ foDet;
+    MulSub(&foDet, &pmx->efM11, &pmx->efM22, &pmx->efM12, &pmx->efM21);
+    return !FLOATOBJ_Equal0(&foDet);
+}
+
+VOID FASTCALL
+MX_Set0(OUT PMATRIX pmx)
+{
+    FLOATOBJ_Set0(&pmx->efM11);
+    FLOATOBJ_Set0(&pmx->efM12);
+    FLOATOBJ_Set0(&pmx->efM21);
+    FLOATOBJ_Set0(&pmx->efM22);
+    FLOATOBJ_Set0(&pmx->efDx);
+    FLOATOBJ_Set0(&pmx->efDy);
+}
+
 /*
  * A^-1 = adj(A) / det(AT)
  * A^-1 = 1/(a*d - b*c) * (a22,-a12,a21,-a11)
index 0c3ff2e..179890d 100644 (file)
@@ -74,3 +74,6 @@ XFORMOBJ_bApplyXform(
     IN ULONG cPoints,
     IN PVOID pvIn,
     OUT PVOID pvOut);
+
+BOOL FASTCALL MX_IsInvertible(IN PMATRIX pmx);
+VOID FASTCALL MX_Set0(OUT PMATRIX pmx);