[WIN32SS][NTGDI][GDI32] Fix DPtoLP and NtGdiTransformPoints etc. (#1540)

Fix NtGdiTransformPoints, gdi32!DPtoLP, gdi32!LPtoDP and gdi32!SetMapMode functions. Fix CORE-15983. CORE-15983
This commit is contained in:
Katayama Hirofumi MZ 2019-04-29 14:45:44 +09:00 committed by GitHub
parent 45ec49ca2f
commit 8bdfdd5c17
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 35 deletions

View file

@ -171,28 +171,35 @@ DPtoLP(
_Inout_updates_(nCount) LPPOINT lpPoints, _Inout_updates_(nCount) LPPOINT lpPoints,
_In_ INT nCount) _In_ INT nCount)
{ {
#if 0
INT i;
PDC_ATTR pdcattr; PDC_ATTR pdcattr;
SIZEL sizlView;
/* Get the DC attribute */ if (nCount <= 0)
pdcattr = GdiGetDcAttr(hdc); return TRUE;
if (!pdcattr)
if (hdc == NULL)
{ {
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
} }
if (lpPoints == NULL)
if (pdcattr->flXform & ANY_XFORM_CHANGES)
{ {
GdiFixupTransforms(pdcattr); return TRUE;
} }
// FIXME: can this fail on Windows? pdcattr = GdiGetDcAttr(hdc);
GdiTransformPoints(&pdcattr->mxDeviceToWorld, lpPoints, lpPoints, nCount); 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); return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiDpToLp);
} }
@ -203,28 +210,25 @@ LPtoDP(
_Inout_updates_(nCount) LPPOINT lpPoints, _Inout_updates_(nCount) LPPOINT lpPoints,
_In_ INT nCount) _In_ INT nCount)
{ {
#if 0
INT i;
PDC_ATTR pdcattr; PDC_ATTR pdcattr;
/* Get the DC attribute */ if (nCount <= 0)
pdcattr = GdiGetDcAttr(hdc); return TRUE;
if (!pdcattr)
if (hdc == NULL)
{ {
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
} }
if (lpPoints == NULL)
if (pdcattr->flXform & ANY_XFORM_CHANGES)
{ {
GdiFixupTransforms(pdcattr); return TRUE;
} }
// FIXME: can this fail on Windows? pdcattr = GdiGetDcAttr(hdc);
GdiTransformPoints(&pdcattr->mxWorldToDevice, lpPoints, lpPoints, nCount); if (pdcattr == NULL)
return FALSE;
return TRUE;
#endif
return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiLpToDp); return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiLpToDp);
} }
@ -490,6 +494,9 @@ SetViewportExtEx(
(pdcattr->szlViewportExt.cy == nYExtent)) (pdcattr->szlViewportExt.cy == nYExtent))
return TRUE; return TRUE;
if (nXExtent == 0 || nYExtent == 0)
return TRUE;
/* Only change viewport extension if we are in iso or aniso mode */ /* Only change viewport extension if we are in iso or aniso mode */
if ((pdcattr->iMapMode == MM_ISOTROPIC) || if ((pdcattr->iMapMode == MM_ISOTROPIC) ||
(pdcattr->iMapMode == MM_ANISOTROPIC)) (pdcattr->iMapMode == MM_ANISOTROPIC))
@ -512,7 +519,8 @@ SetViewportExtEx(
NtGdiMirrorWindowOrg(hdc); NtGdiMirrorWindowOrg(hdc);
/* Update xform flags */ /* 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; return TRUE;

View file

@ -3,7 +3,8 @@
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* PURPOSE: Coordinate systems * PURPOSE: Coordinate systems
* FILE: win32ss/gdi/ntgdi/coord.c * 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 /* Coordinate translation overview
@ -195,7 +196,7 @@ DC_vUpdateWorldToDevice(PDC pdc)
XFORMOBJ_iCombine(&xoWorldToDevice, &xoWorldToPage, &xoPageToDevice); XFORMOBJ_iCombine(&xoWorldToDevice, &xoWorldToPage, &xoPageToDevice);
/* Reset the flags */ /* Reset the flags */
pdc->pdcattr->flXform &= ~(PAGE_XLATE_CHANGED|PAGE_EXTENTS_CHANGED|WORLD_XFORM_CHANGED); pdc->pdcattr->flXform &= ~WORLD_XFORM_CHANGED;
} }
VOID VOID
@ -213,7 +214,7 @@ DC_vUpdateDeviceToWorld(PDC pdc)
XFORMOBJ_vInit(&xoDeviceToWorld, &pdc->pdcattr->mxDeviceToWorld); XFORMOBJ_vInit(&xoDeviceToWorld, &pdc->pdcattr->mxDeviceToWorld);
if (XFORMOBJ_iInverse(&xoDeviceToWorld, &xoWorldToDevice) == DDI_ERROR) if (XFORMOBJ_iInverse(&xoDeviceToWorld, &xoWorldToDevice) == DDI_ERROR)
{ {
// FIXME: do we need to reset anything? MX_Set0(&pdc->pdcattr->mxDeviceToWorld);
return; return;
} }
@ -377,10 +378,14 @@ NtGdiTransformPoints(
if (Count <= 0) if (Count <= 0)
return TRUE; return TRUE;
if (!UnsafePtsIn || !UnsafePtOut)
{
return FALSE;
}
pdc = DC_LockDc(hDC); pdc = DC_LockDc(hDC);
if (!pdc) if (!pdc)
{ {
EngSetLastError(ERROR_INVALID_PARAMETER);
return FALSE; return FALSE;
} }
@ -595,7 +600,7 @@ NtGdiOffsetViewportOrgEx(
} }
pdcattr->ptlViewportOrg.x += XOffset; pdcattr->ptlViewportOrg.x += XOffset;
pdcattr->ptlViewportOrg.y += YOffset; pdcattr->ptlViewportOrg.y += YOffset;
pdcattr->flXform |= PAGE_XLATE_CHANGED; pdcattr->flXform |= PAGE_XLATE_CHANGED | DEVICE_TO_WORLD_INVALID;
DC_UnlockDc(dc); DC_UnlockDc(dc);
@ -821,6 +826,9 @@ IntGdiSetMapMode(
FLONG flXform; FLONG flXform;
PDC_ATTR pdcattr = dc->pdcattr; PDC_ATTR pdcattr = dc->pdcattr;
if (MapMode == pdcattr->iMapMode)
return MapMode;
flXform = pdcattr->flXform & ~(ISO_OR_ANISO_MAP_MODE|PTOD_EFM22_NEGATIVE| flXform = pdcattr->flXform & ~(ISO_OR_ANISO_MAP_MODE|PTOD_EFM22_NEGATIVE|
PTOD_EFM11_NEGATIVE|POSITIVE_Y_IS_UP|PAGE_TO_DEVICE_SCALE_IDENTITY| PTOD_EFM11_NEGATIVE|POSITIVE_Y_IS_UP|PAGE_TO_DEVICE_SCALE_IDENTITY|
PAGE_TO_DEVICE_IDENTITY); PAGE_TO_DEVICE_IDENTITY);
@ -921,7 +929,7 @@ GreSetViewportOrgEx(
pdcattr->ptlViewportOrg.x = X; pdcattr->ptlViewportOrg.x = X;
pdcattr->ptlViewportOrg.y = Y; pdcattr->ptlViewportOrg.y = Y;
pdcattr->flXform |= PAGE_XLATE_CHANGED; pdcattr->flXform |= PAGE_XLATE_CHANGED | DEVICE_TO_WORLD_INVALID;
DC_UnlockDc(dc); DC_UnlockDc(dc);
return TRUE; return TRUE;
@ -972,7 +980,7 @@ NtGdiSetViewportOrgEx(
pdcattr->ptlViewportOrg.x = X; pdcattr->ptlViewportOrg.x = X;
pdcattr->ptlViewportOrg.y = Y; pdcattr->ptlViewportOrg.y = Y;
pdcattr->flXform |= PAGE_XLATE_CHANGED; pdcattr->flXform |= PAGE_XLATE_CHANGED | DEVICE_TO_WORLD_INVALID;
DC_UnlockDc(dc); DC_UnlockDc(dc);
@ -1024,7 +1032,7 @@ NtGdiSetWindowOrgEx(
pdcattr->ptlWindowOrg.x = X; pdcattr->ptlWindowOrg.x = X;
pdcattr->ptlWindowOrg.y = Y; pdcattr->ptlWindowOrg.y = Y;
pdcattr->flXform |= PAGE_XLATE_CHANGED; pdcattr->flXform |= PAGE_XLATE_CHANGED | DEVICE_TO_WORLD_INVALID;
DC_UnlockDc(dc); DC_UnlockDc(dc);
@ -1060,7 +1068,7 @@ IntMirrorWindowOrg(PDC dc)
X = (X * pdcattr->szlWindowExt.cx) / cx; X = (X * pdcattr->szlWindowExt.cx) / cx;
pdcattr->ptlWindowOrg.x = pdcattr->lWindowOrgx - X; // Now set the inverted win origion. 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; return;
} }

View file

@ -131,6 +131,9 @@ DC_vXformDeviceToWorld(
PMATRIX pmx; PMATRIX pmx;
pmx = DC_pmxDeviceToWorld(pdc); pmx = DC_pmxDeviceToWorld(pdc);
if (!MX_IsInvertible(pmx))
return;
XFORMOBJ_vInit(&xo, pmx); XFORMOBJ_vInit(&xo, pmx);
XFORMOBJ_bApplyXform(&xo, XF_LTOL, cNumPoints, pptlDest, pptlSource); XFORMOBJ_bApplyXform(&xo, XF_LTOL, cNumPoints, pptlDest, pptlSource);
} }

View file

@ -3,7 +3,8 @@
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL - See COPYING in the top level directory
* FILE: win32ss/gdi/ntgdi/xformobj.c * FILE: win32ss/gdi/ntgdi/xformobj.c
* PURPOSE: XFORMOBJ API * PURPOSE: XFORMOBJ API
* PROGRAMMER: Timo Kreuzer * PROGRAMMERS: Timo Kreuzer
* Katayama Hirofumi MZ
*/ */
/** Includes ******************************************************************/ /** 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 = adj(A) / det(AT)
* A^-1 = 1/(a*d - b*c) * (a22,-a12,a21,-a11) * A^-1 = 1/(a*d - b*c) * (a22,-a12,a21,-a11)

View file

@ -74,3 +74,6 @@ XFORMOBJ_bApplyXform(
IN ULONG cPoints, IN ULONG cPoints,
IN PVOID pvIn, IN PVOID pvIn,
OUT PVOID pvOut); OUT PVOID pvOut);
BOOL FASTCALL MX_IsInvertible(IN PMATRIX pmx);
VOID FASTCALL MX_Set0(OUT PMATRIX pmx);