mirror of
https://github.com/reactos/reactos.git
synced 2025-02-20 15:35:04 +00:00
[WIN32K]
- Rewrite coordinate transformation code to use XFORMOBJ apis instead of using floating point in kernel mode. As a small present fix 14 gdi32_winetests (5 mapping, 9 bitmap) I disabled some RtoL code, since it didn't work anyway and caused more bugs than it fixed. svn path=/trunk/; revision=56236
This commit is contained in:
parent
4cde806076
commit
6539718c1d
10 changed files with 476 additions and 298 deletions
|
@ -100,10 +100,16 @@ typedef enum _TRANSFORMTYPE
|
|||
/* MATRIX flAccel flags */
|
||||
enum
|
||||
{
|
||||
MX_SCALE = 1,
|
||||
MX_IDENTITYSCALE = 2,
|
||||
MX_INTEGER = 4,
|
||||
MX_NOTRANSLATE = 8,
|
||||
XFORM_SCALE = 1,
|
||||
XFORM_UNITY = 2,
|
||||
XFORM_Y_NEG = 4,
|
||||
XFORM_FORMAT_LTOFX = 8,
|
||||
XFORM_FORMAT_FXTOL = 0x10,
|
||||
XFORM_FORMAT_LTOL = 0x20,
|
||||
XFORM_NO_TRANSLATION = 0x40,
|
||||
|
||||
/* Reactos specific */
|
||||
XFORM_INTEGER = 0x1000,
|
||||
};
|
||||
|
||||
typedef enum GDIObjType
|
||||
|
@ -548,7 +554,7 @@ typedef VOID (APIENTRY *PFN_DrvMovePanning)(LONG, LONG, FLONG);
|
|||
//
|
||||
typedef struct _DRIVER_FUNCTIONS
|
||||
{
|
||||
PFN_DrvEnablePDEV EnablePDEV;
|
||||
PFN_DrvEnablePDEV EnablePDEV;
|
||||
PFN_DrvCompletePDEV CompletePDEV;
|
||||
PFN_DrvDisablePDEV DisablePDEV;
|
||||
PFN_DrvEnableSurface EnableSurface;
|
||||
|
@ -584,10 +590,10 @@ typedef struct _DRIVER_FUNCTIONS
|
|||
PFN_DrvStartPage StartPage;
|
||||
PFN_DrvEndDoc EndDoc;
|
||||
PFN_DrvStartDoc StartDoc;
|
||||
PVOID Unknown3;
|
||||
PVOID Unknown3;
|
||||
PFN_DrvGetGlyphMode GetGlyphMode;
|
||||
PFN_DrvSynchronize Synchronize;
|
||||
PVOID Unknown4;
|
||||
PVOID Unknown4;
|
||||
PFN_DrvSaveScreenBits SaveScreenBits;
|
||||
PFN_DrvGetModes GetModes;
|
||||
PFN_DrvFree Free;
|
||||
|
@ -641,7 +647,7 @@ typedef struct _DRIVER_FUNCTIONS
|
|||
PVOID Reserved9;
|
||||
PVOID Reserved10;
|
||||
PVOID Reserved11; /* 92 */
|
||||
|
||||
|
||||
/* ReactOS specify */
|
||||
PFN_DrvEnableDriver EnableDriver; //ReactOS Extra
|
||||
} DRIVER_FUNCTIONS, *PDRIVER_FUNCTIONS;
|
||||
|
|
|
@ -81,6 +81,22 @@
|
|||
#define PARAM1 8
|
||||
#define PARAM2 12
|
||||
|
||||
/** Globals **/
|
||||
/* extern const FLOATOBJ gef0; */
|
||||
PUBLIC _gef0
|
||||
_gef0:
|
||||
.long 0, 0
|
||||
|
||||
/* extern const FLOATOBJ gef1; */
|
||||
PUBLIC _gef1
|
||||
_gef1:
|
||||
.long HEX(40000000), HEX(00000002)
|
||||
|
||||
/* extern const FLOATOBJ gef16; */
|
||||
PUBLIC _gef16
|
||||
_gef16:
|
||||
.long HEX(40000000), HEX(00000006)
|
||||
|
||||
/******************************************************************************
|
||||
* VOID
|
||||
* APIENTRY
|
||||
|
|
|
@ -45,8 +45,72 @@ InvertXform(
|
|||
XFORMOBJ_iGetXform(&xo, pxformDest);
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_vFixIsotropicMapping(PDC pdc);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_vUpdateWorldToDevice(PDC pdc);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_vUpdateDeviceToWorld(PDC pdc);
|
||||
|
||||
PSIZEL
|
||||
FORCEINLINE
|
||||
DC_pszlViewportExt(PDC pdc)
|
||||
{
|
||||
PDC_ATTR pdcattr = pdc->pdcattr;
|
||||
|
||||
/* Check if we need isotropic fixup */
|
||||
if ((pdcattr->flXform & PAGE_EXTENTS_CHANGED) &&
|
||||
(pdcattr->iMapMode == MM_ISOTROPIC))
|
||||
{
|
||||
/* Fixup viewport extension */
|
||||
DC_vFixIsotropicMapping(pdc);
|
||||
}
|
||||
|
||||
return &pdcattr->szlViewportExt;
|
||||
}
|
||||
|
||||
PMATRIX
|
||||
FORCEINLINE
|
||||
DC_pmxWorldToPage(PDC pdc)
|
||||
{
|
||||
return &pdc->pdcattr->mxWorldToPage;
|
||||
}
|
||||
|
||||
PMATRIX
|
||||
FORCEINLINE
|
||||
DC_pmxWorldToDevice(PDC pdc)
|
||||
{
|
||||
/* Check if world or page xform was changed */
|
||||
if (pdc->pdcattr->flXform & (PAGE_XLATE_CHANGED|PAGE_EXTENTS_CHANGED|WORLD_XFORM_CHANGED))
|
||||
{
|
||||
/* Update the world-to-device xform */
|
||||
DC_vUpdateWorldToDevice(pdc);
|
||||
}
|
||||
|
||||
return &pdc->pdcattr->mxWorldToDevice;
|
||||
}
|
||||
|
||||
PMATRIX
|
||||
FORCEINLINE
|
||||
DC_pmxDeviceToWorld(PDC pdc)
|
||||
{
|
||||
/* Check if the device-to-world xform is invalid */
|
||||
if (pdc->pdcattr->flXform & DEVICE_TO_WORLD_INVALID)
|
||||
{
|
||||
/* Update the world-to-device xform */
|
||||
DC_vUpdateDeviceToWorld(pdc);
|
||||
}
|
||||
|
||||
return &pdc->pdcattr->mxDeviceToWorld;
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
void
|
||||
DC_vXformDeviceToWorld(
|
||||
IN PDC pdc,
|
||||
IN ULONG cNumPoints,
|
||||
|
@ -54,13 +118,15 @@ DC_vXformDeviceToWorld(
|
|||
IN PPOINTL pptlSource)
|
||||
{
|
||||
XFORMOBJ xo;
|
||||
PMATRIX pmx;
|
||||
|
||||
XFORMOBJ_vInit(&xo, &pdc->dclevel.mxDeviceToWorld);
|
||||
pmx = DC_pmxDeviceToWorld(pdc);
|
||||
XFORMOBJ_vInit(&xo, pmx);
|
||||
XFORMOBJ_bApplyXform(&xo, XF_LTOL, cNumPoints, pptlDest, pptlSource);
|
||||
}
|
||||
|
||||
VOID
|
||||
FORCEINLINE
|
||||
void
|
||||
DC_vXformWorldToDevice(
|
||||
IN PDC pdc,
|
||||
IN ULONG cNumPoints,
|
||||
|
@ -68,18 +134,27 @@ DC_vXformWorldToDevice(
|
|||
IN PPOINTL pptlSource)
|
||||
{
|
||||
XFORMOBJ xo;
|
||||
PMATRIX pmx;
|
||||
|
||||
XFORMOBJ_vInit(&xo, &pdc->dclevel.mxWorldToDevice);
|
||||
pmx = DC_pmxWorldToDevice(pdc);
|
||||
XFORMOBJ_vInit(&xo, pmx);
|
||||
XFORMOBJ_bApplyXform(&xo, XF_LTOL, cNumPoints, pptlDest, pptlSource);
|
||||
}
|
||||
|
||||
int APIENTRY IntGdiSetMapMode(PDC, int);
|
||||
|
||||
BOOL NTAPI
|
||||
IntGdiCombineTransform(
|
||||
XFORML *pxformDest,
|
||||
XFORML *pxform1,
|
||||
XFORML *pxform2);
|
||||
|
||||
BOOL
|
||||
FASTCALL
|
||||
IntGdiModifyWorldTransform(PDC pDc,
|
||||
CONST LPXFORM lpXForm,
|
||||
DWORD Mode);
|
||||
NTAPI
|
||||
GreModifyWorldTransform(
|
||||
PDC pdc,
|
||||
const XFORML *pXForm,
|
||||
DWORD dwMode);
|
||||
|
||||
VOID FASTCALL IntMirrorWindowOrg(PDC);
|
||||
void FASTCALL IntFixIsotropicMapping(PDC);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#if defined(_X86_)
|
||||
#if defined(_M_IX86)
|
||||
|
||||
FORCEINLINE
|
||||
BOOL
|
||||
|
@ -54,6 +54,15 @@ _FLOATOBJ_Equal1(FLOATOBJ *pf)
|
|||
return (pef->lMant == 0x40000000 && pef->lExp == 2);
|
||||
}
|
||||
|
||||
extern const FLOATOBJ gef0;
|
||||
extern const FLOATOBJ gef1;
|
||||
extern const FLOATOBJ gef16;
|
||||
|
||||
#define FLOATOBJ_0 {0x00000000, 0x00000000}
|
||||
#define FLOATOBJ_1 {0x40000000, 0x00000002}
|
||||
#define FLOATOBJ_16 {0x40000000, 0x00000006}
|
||||
#define FLOATOBJ_1_16 {0x40000000, 0xfffffffe}
|
||||
|
||||
#define FLOATOBJ_Set0(fo) (fo)->ul1 = 0; (fo)->ul2 = 0;
|
||||
#define FLOATOBJ_Set1(fo) (fo)->ul1 = 0x40000000; (fo)->ul2 = 2;
|
||||
|
||||
|
@ -66,7 +75,16 @@ _FLOATOBJ_Equal1(FLOATOBJ *pf)
|
|||
#define _FLOATOBJ_Equal1(pf) (*(pf) == 1.)
|
||||
#define _FLOATOBJ_GetFix(pf) ((LONG)(*(pf) * 16.))
|
||||
|
||||
#define FLOATOBJ_Set0(fo) *(fo) = 0;
|
||||
#define FLOATOBJ_0 0.
|
||||
#define FLOATOBJ_1 1.
|
||||
#define FLOATOBJ_16 16.
|
||||
#define FLOATOBJ_1_16 (1./16.)
|
||||
|
||||
#define gef0 FLOATOBJ_0
|
||||
#define gef1 FLOATOBJ_1
|
||||
#define gef16 FLOATOBJ_16
|
||||
|
||||
#define FLOATOBJ_Set0(fo) *(fo) = 0;
|
||||
#define FLOATOBJ_Set1(fo) *(fo) = 1;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -80,13 +80,6 @@ IntGdiCreateDC(PUNICODE_STRING Driver,
|
|||
CONST PDEVMODEW InitData,
|
||||
BOOL CreateAsIC);
|
||||
|
||||
/* Coord functions */
|
||||
|
||||
BOOL FASTCALL
|
||||
IntGdiCombineTransform(LPXFORM XFormResult,
|
||||
LPXFORM xform1,
|
||||
LPXFORM xform2);
|
||||
|
||||
/* Stock objects */
|
||||
|
||||
VOID FASTCALL
|
||||
|
|
|
@ -3,7 +3,65 @@
|
|||
* PROJECT: ReactOS kernel
|
||||
* PURPOSE: Coordinate systems
|
||||
* FILE: subsystems/win32/win32k/objects/coord.c
|
||||
* PROGRAMER: Unknown
|
||||
* PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
|
||||
*/
|
||||
|
||||
/* Coordinate translation overview
|
||||
* -------------------------------
|
||||
*
|
||||
* Windows uses 3 different coordinate systems, referred to as world space,
|
||||
* page space and device space.
|
||||
*
|
||||
* Device space:
|
||||
* This is the coordinate system of the physical device that displays the
|
||||
* graphics. One unit matches one pixel of the surface. The coordinate system
|
||||
* is always orthogonal.
|
||||
*
|
||||
* Page space:
|
||||
* This is the coordinate system on the screen or on the paper layout for
|
||||
* printer devices. The coordinate system is also orthogonal but one unit
|
||||
* does not neccesarily match one pixel. Instead there are different mapping
|
||||
* modes that can be set using SetMapMode() that specify how page space units
|
||||
* are transformed into device space units. These mapping modes are:
|
||||
* - MM_TEXT: One unit matches one unit in device space (one pixel)
|
||||
* - MM_TWIPS One unit matches 1/20 point (1/1440 inch)
|
||||
* - MM_LOMETRIC: One unit matches 0.1 millimeter
|
||||
* - MM_HIMETRIC: One unit matches 0.01 millimeter
|
||||
* - MM_LOENGLISH: One unit matches 0.01 inch
|
||||
* - MM_HIENGLISH: One unit matches 0.001 inch
|
||||
* - MM_ISOTROPIC:
|
||||
* - MM_ANISOTROPIC:
|
||||
* If the mapping mode is either MM_ISOTROPIC or MM_ANISOTROPIC, the actual
|
||||
* transormation is calculated from the window and viewport extension.
|
||||
* The window extension can be set using SetWindowExtEx() and describes the
|
||||
* extents of an arbitrary window (not to confuse with the gui element!) in
|
||||
* page space coordinates.
|
||||
* The viewport extension can be set using SetViewportExtEx() and describes
|
||||
* the extent of the same window in device space coordinates. If the mapping
|
||||
* mode is MM_ISOTROPIC one of the viewport extensions can be adjusted by GDI
|
||||
* to make sure the mapping stays isotropic, that is it has the same x/y ratio
|
||||
* as the window extension.
|
||||
*
|
||||
* World space:
|
||||
* World space is the coordinate system that is used for all GDI drawing
|
||||
* operations. The metrics of this coordinate system depend on the DCs
|
||||
* graphics mode, which can be set using SetGraphicsMode().
|
||||
* If the graphics mode is GM_COMPATIBLE, world space is identical to page
|
||||
* space and no additional transformation is applied.
|
||||
* If the graphics mode is GM_ADVANCED, an arbitrary coordinate transformation
|
||||
* can be set using SetWorldTransform(), which is applied to transform world
|
||||
* space coordinates into page space coordinates.
|
||||
*
|
||||
* User mode data
|
||||
* All coordinate translation data is stored in the dc attribute, so the values
|
||||
* might be invalid. This has to be taken into account. Integer values might be
|
||||
* zero, so when a division is made, the value has to be read first and then
|
||||
* checked! For floating point values (FLOATOBJ as well) these restrictions do
|
||||
* not apply, since we cannot get dividy-by-zero exceptions.
|
||||
* Though the result might be a completely random and invalid value, if it was
|
||||
* messed with in an illegal way in user mode. This is not a problem, since the
|
||||
* result of coordinate transformations are never expected to be "valid" values.
|
||||
* In the worst case, the drawing operation draws rubbish into the DC.
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
@ -12,140 +70,183 @@
|
|||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
C_ASSERT(sizeof(XFORML) == sizeof(XFORM));
|
||||
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
const MATRIX gmxIdentity =
|
||||
{
|
||||
FLOATOBJ_1, FLOATOBJ_0,
|
||||
FLOATOBJ_0, FLOATOBJ_1,
|
||||
FLOATOBJ_0, FLOATOBJ_0,
|
||||
0, 0, XFORM_NO_TRANSLATION|XFORM_FORMAT_LTOL|XFORM_UNITY|XFORM_SCALE
|
||||
};
|
||||
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
void FASTCALL
|
||||
IntFixIsotropicMapping(PDC pdc)
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_vFixIsotropicMapping(PDC pdc)
|
||||
{
|
||||
PDC_ATTR pdcattr;
|
||||
LONG fx, fy, s;
|
||||
LONG64 fx, fy;
|
||||
LONG s;
|
||||
SIZEL szlWindowExt, szlViewportExt;
|
||||
ASSERT(pdc->pdcattr->iMapMode == MM_ISOTROPIC);
|
||||
|
||||
/* Get a pointer to the DC_ATTR */
|
||||
pdcattr = pdc->pdcattr;
|
||||
|
||||
/* Read the extents, we rely on non-null values */
|
||||
szlWindowExt = pdcattr->szlWindowExt;
|
||||
szlViewportExt = pdcattr->szlViewportExt;
|
||||
|
||||
/* Check if all values are valid */
|
||||
if (pdcattr->szlWindowExt.cx == 0 || pdcattr->szlWindowExt.cy == 0 ||
|
||||
pdcattr->szlViewportExt.cx == 0 || pdcattr->szlViewportExt.cy == 0)
|
||||
if ((szlWindowExt.cx == 0) || (szlWindowExt.cy == 0) ||
|
||||
(szlViewportExt.cx == 0) || (szlViewportExt.cy == 0))
|
||||
{
|
||||
/* Don't recalculate */
|
||||
/* Someone put rubbish into the fields, just ignore it. */
|
||||
return;
|
||||
}
|
||||
|
||||
fx = abs(pdcattr->szlWindowExt.cx * pdcattr->szlViewportExt.cy);
|
||||
fy = abs(pdcattr->szlWindowExt.cy * pdcattr->szlViewportExt.cx);
|
||||
fx = abs((LONG64)szlWindowExt.cx * szlViewportExt.cy);
|
||||
fy = abs((LONG64)szlWindowExt.cy * szlViewportExt.cx);
|
||||
|
||||
if (fy > fx)
|
||||
if (fx < fy)
|
||||
{
|
||||
s = pdcattr->szlWindowExt.cy * pdcattr->szlViewportExt.cx > 0 ? 1 : -1;
|
||||
pdcattr->szlViewportExt.cx = s * fx / pdcattr->szlWindowExt.cy;
|
||||
s = (szlWindowExt.cy ^ szlViewportExt.cx) > 0 ? 1 : -1;
|
||||
pdcattr->szlViewportExt.cx = (LONG)(fx * s / szlWindowExt.cy);
|
||||
}
|
||||
else if (fx > fy)
|
||||
{
|
||||
s = pdcattr->szlWindowExt.cx * pdcattr->szlViewportExt.cy > 0 ? 1 : -1;
|
||||
pdcattr->szlViewportExt.cy = s * fy / pdcattr->szlWindowExt.cx;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Don't use floating point in the kernel!
|
||||
void IntWindowToViewPort(PDC_ATTR pdcattr, LPXFORM xformWnd2Vport)
|
||||
{
|
||||
FLOAT scaleX, scaleY;
|
||||
|
||||
scaleX = (pdcattr->szlWindowExt.cx ? (FLOAT)pdcattr->szlViewportExt.cx / (FLOAT)pdcattr->szlWindowExt.cx : 0.0f);
|
||||
scaleY = (pdcattr->szlWindowExt.cy ? (FLOAT)pdcattr->szlViewportExt.cy / (FLOAT)pdcattr->szlWindowExt.cy : 0.0f);
|
||||
xformWnd2Vport->eM11 = scaleX;
|
||||
xformWnd2Vport->eM12 = 0.0;
|
||||
xformWnd2Vport->eM21 = 0.0;
|
||||
xformWnd2Vport->eM22 = scaleY;
|
||||
xformWnd2Vport->eDx = (FLOAT)pdcattr->ptlViewportOrg.x - scaleX * (FLOAT)pdcattr->ptlWindowOrg.x;
|
||||
xformWnd2Vport->eDy = (FLOAT)pdcattr->ptlViewportOrg.y - scaleY * (FLOAT)pdcattr->ptlWindowOrg.y;
|
||||
}
|
||||
|
||||
// FIXME: Use XFORMOBJECT!
|
||||
VOID FASTCALL
|
||||
DC_UpdateXforms(PDC dc)
|
||||
{
|
||||
XFORM xformWnd2Vport;
|
||||
PDC_ATTR pdcattr = dc->pdcattr;
|
||||
XFORM xformWorld2Vport, xformWorld2Wnd, xformVport2World;
|
||||
|
||||
/* Construct a transformation to do the window-to-viewport conversion */
|
||||
IntWindowToViewPort(pdcattr, &xformWnd2Vport);
|
||||
|
||||
/* Combine with the world transformation */
|
||||
MatrixS2XForm(&xformWorld2Vport, &dc->dclevel.mxWorldToDevice);
|
||||
MatrixS2XForm(&xformWorld2Wnd, &dc->dclevel.mxWorldToPage);
|
||||
IntGdiCombineTransform(&xformWorld2Vport, &xformWorld2Wnd, &xformWnd2Vport);
|
||||
|
||||
/* Create inverse of world-to-viewport transformation */
|
||||
MatrixS2XForm(&xformVport2World, &dc->dclevel.mxDeviceToWorld);
|
||||
if (DC_InvertXform(&xformWorld2Vport, &xformVport2World))
|
||||
{
|
||||
pdcattr->flXform &= ~DEVICE_TO_WORLD_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
pdcattr->flXform |= DEVICE_TO_WORLD_INVALID;
|
||||
s = (szlWindowExt.cx ^ szlViewportExt.cy) > 0 ? 1 : -1;
|
||||
pdcattr->szlViewportExt.cy = (LONG)(fy * s / szlWindowExt.cx);
|
||||
}
|
||||
|
||||
/* Update transformation matrices */
|
||||
XForm2MatrixS(&dc->dclevel.mxWorldToDevice, &xformWorld2Vport);
|
||||
XForm2MatrixS(&dc->dclevel.mxDeviceToWorld, &xformVport2World);
|
||||
/* Reset the flag */
|
||||
pdc->pdcattr->flXform &= ~PAGE_EXTENTS_CHANGED;
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_vUpdateViewportExt(PDC pdc)
|
||||
DC_vGetPageToDevice(PDC pdc, MATRIX *pmx)
|
||||
{
|
||||
PDC_ATTR pdcattr;
|
||||
PDC_ATTR pdcattr = pdc->pdcattr;
|
||||
PSIZEL pszlViewPortExt;
|
||||
|
||||
/* Get a pointer to the dc attribute */
|
||||
pdcattr = pdc->pdcattr;
|
||||
/* Get the viewport extension */
|
||||
pszlViewPortExt = DC_pszlViewportExt(pdc);
|
||||
|
||||
/* Check if we need to recalculate */
|
||||
if (pdcattr->flXform & PAGE_EXTENTS_CHANGED)
|
||||
/* No shearing / rotation */
|
||||
FLOATOBJ_SetLong(&pmx->efM12, 0);
|
||||
FLOATOBJ_SetLong(&pmx->efM21, 0);
|
||||
|
||||
/* Calculate scaling */
|
||||
if (pdcattr->szlWindowExt.cx != 0)
|
||||
{
|
||||
/* Check if we need to do isotropic fixup */
|
||||
if (pdcattr->iMapMode == MM_ISOTROPIC)
|
||||
{
|
||||
IntFixIsotropicMapping(pdc);
|
||||
}
|
||||
|
||||
/* Update xforms, CHECKME: really done here? */
|
||||
DC_UpdateXforms(pdc);
|
||||
FLOATOBJ_SetLong(&pmx->efM11, pszlViewPortExt->cx);
|
||||
FLOATOBJ_DivLong(&pmx->efM11, pdcattr->szlWindowExt.cx);
|
||||
}
|
||||
else
|
||||
FLOATOBJ_SetLong(&pmx->efM11, 1);
|
||||
|
||||
if (pdcattr->szlWindowExt.cy != 0)
|
||||
{
|
||||
FLOATOBJ_SetLong(&pmx->efM22, pszlViewPortExt->cy);
|
||||
FLOATOBJ_DivLong(&pmx->efM22, pdcattr->szlWindowExt.cy);
|
||||
}
|
||||
else
|
||||
FLOATOBJ_SetLong(&pmx->efM22, 1);
|
||||
|
||||
/* Calculate x offset */
|
||||
FLOATOBJ_SetLong(&pmx->efDx, -pdcattr->ptlWindowOrg.x);
|
||||
FLOATOBJ_Mul(&pmx->efDx, &pmx->efM11);
|
||||
FLOATOBJ_AddLong(&pmx->efDx, pdcattr->ptlViewportOrg.x);
|
||||
|
||||
/* Calculate y offset */
|
||||
FLOATOBJ_SetLong(&pmx->efDy, -pdcattr->ptlWindowOrg.y);
|
||||
FLOATOBJ_Mul(&pmx->efDy, &pmx->efM22);
|
||||
FLOATOBJ_AddLong(&pmx->efDy, pdcattr->ptlViewportOrg.y);
|
||||
}
|
||||
|
||||
// FIXME: Don't use floating point in the kernel! use XFORMOBJ function
|
||||
BOOL FASTCALL
|
||||
IntGdiCombineTransform(
|
||||
LPXFORM XFormResult,
|
||||
LPXFORM xform1,
|
||||
LPXFORM xform2)
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_vUpdateWorldToDevice(PDC pdc)
|
||||
{
|
||||
XFORM xformTemp;
|
||||
XFORMOBJ xoPageToDevice, xoWorldToPage, xoWorldToDevice;
|
||||
MATRIX mxPageToDevice;
|
||||
|
||||
/* Check for illegal parameters */
|
||||
if (!XFormResult || !xform1 || !xform2)
|
||||
// FIXME: make sure world-to-page is valid!
|
||||
|
||||
/* Construct a transformation to do the page-to-device conversion */
|
||||
DC_vGetPageToDevice(pdc, &mxPageToDevice);
|
||||
XFORMOBJ_vInit(&xoPageToDevice, &mxPageToDevice);
|
||||
|
||||
/* Recalculate the world-to-device xform */
|
||||
XFORMOBJ_vInit(&xoWorldToPage, &pdc->pdcattr->mxWorldToPage);
|
||||
XFORMOBJ_vInit(&xoWorldToDevice, &pdc->pdcattr->mxWorldToDevice);
|
||||
XFORMOBJ_iCombine(&xoWorldToDevice, &xoWorldToPage, &xoPageToDevice);
|
||||
|
||||
/* Reset the flags */
|
||||
pdc->pdcattr->flXform &= ~(PAGE_XLATE_CHANGED|PAGE_EXTENTS_CHANGED|WORLD_XFORM_CHANGED);
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
DC_vUpdateDeviceToWorld(PDC pdc)
|
||||
{
|
||||
XFORMOBJ xoWorldToDevice, xoDeviceToWorld;
|
||||
PMATRIX pmxWorldToDevice;
|
||||
|
||||
/* Get the world-to-device translation */
|
||||
pmxWorldToDevice = DC_pmxWorldToDevice(pdc);
|
||||
XFORMOBJ_vInit(&xoWorldToDevice, pmxWorldToDevice);
|
||||
|
||||
/* Create inverse of world-to-device transformation */
|
||||
XFORMOBJ_vInit(&xoDeviceToWorld, &pdc->pdcattr->mxDeviceToWorld);
|
||||
if (XFORMOBJ_iInverse(&xoDeviceToWorld, &xoWorldToDevice) == DDI_ERROR)
|
||||
{
|
||||
return FALSE;
|
||||
// FIXME: do we need to reset anything?
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create the result in a temporary XFORM, since xformResult may be
|
||||
* equal to xform1 or xform2 */
|
||||
xformTemp.eM11 = xform1->eM11 * xform2->eM11 + xform1->eM12 * xform2->eM21;
|
||||
xformTemp.eM12 = xform1->eM11 * xform2->eM12 + xform1->eM12 * xform2->eM22;
|
||||
xformTemp.eM21 = xform1->eM21 * xform2->eM11 + xform1->eM22 * xform2->eM21;
|
||||
xformTemp.eM22 = xform1->eM21 * xform2->eM12 + xform1->eM22 * xform2->eM22;
|
||||
xformTemp.eDx = xform1->eDx * xform2->eM11 + xform1->eDy * xform2->eM21 + xform2->eDx;
|
||||
xformTemp.eDy = xform1->eDx * xform2->eM12 + xform1->eDy * xform2->eM22 + xform2->eDy;
|
||||
*XFormResult = xformTemp;
|
||||
/* Reset the flag */
|
||||
pdc->pdcattr->flXform &= ~DEVICE_TO_WORLD_INVALID;
|
||||
}
|
||||
|
||||
BOOL
|
||||
NTAPI
|
||||
GreCombineTransform(
|
||||
XFORML *pxformDest,
|
||||
XFORML *pxform1,
|
||||
XFORML *pxform2)
|
||||
{
|
||||
MATRIX mxDest, mx1, mx2;
|
||||
XFORMOBJ xoDest, xo1, xo2;
|
||||
|
||||
/* Check for illegal parameters */
|
||||
if (!pxformDest || !pxform1 || !pxform2) return FALSE;
|
||||
|
||||
/* Initialize XFORMOBJs */
|
||||
XFORMOBJ_vInit(&xoDest, &mxDest);
|
||||
XFORMOBJ_vInit(&xo1, &mx1);
|
||||
XFORMOBJ_vInit(&xo2, &mx2);
|
||||
|
||||
/* Convert the XFORMLs into XFORMOBJs */
|
||||
XFORMOBJ_iSetXform(&xo1, pxform1);
|
||||
XFORMOBJ_iSetXform(&xo2, pxform2);
|
||||
|
||||
/* Combine them */
|
||||
XFORMOBJ_iCombine(&xoDest, &xo1, &xo2);
|
||||
|
||||
/* Translate back into XFORML */
|
||||
XFORMOBJ_iGetXform(&xoDest, pxformDest);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// FIXME: Should be XFORML and use XFORMOBJ functions
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtGdiCombineTransform(
|
||||
|
@ -160,9 +261,9 @@ NtGdiCombineTransform(
|
|||
ProbeForWrite(UnsafeXFormResult, sizeof(XFORM), 1);
|
||||
ProbeForRead(Unsafexform1, sizeof(XFORM), 1);
|
||||
ProbeForRead(Unsafexform2, sizeof(XFORM), 1);
|
||||
Ret = IntGdiCombineTransform(UnsafeXFormResult,
|
||||
Unsafexform1,
|
||||
Unsafexform2);
|
||||
Ret = GreCombineTransform((XFORML*)UnsafeXFormResult,
|
||||
(XFORML*)Unsafexform1,
|
||||
(XFORML*)Unsafexform2);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
|
@ -177,61 +278,71 @@ NtGdiCombineTransform(
|
|||
BOOL
|
||||
APIENTRY
|
||||
NtGdiGetTransform(
|
||||
HDC hDC,
|
||||
HDC hdc,
|
||||
DWORD iXform,
|
||||
LPXFORM XForm)
|
||||
LPXFORM pXForm)
|
||||
{
|
||||
PDC pdc;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
BOOL ret = TRUE;
|
||||
MATRIX mxPageToDevice;
|
||||
XFORMOBJ xo;
|
||||
PMATRIX pmx;
|
||||
|
||||
if (!XForm)
|
||||
if (!pXForm)
|
||||
{
|
||||
EngSetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pdc = DC_LockDc(hDC);
|
||||
pdc = DC_LockDc(hdc);
|
||||
if (!pdc)
|
||||
{
|
||||
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (iXform)
|
||||
{
|
||||
case GdiWorldSpaceToPageSpace:
|
||||
pmx = DC_pmxWorldToPage(pdc);
|
||||
break;
|
||||
|
||||
case GdiWorldSpaceToDeviceSpace:
|
||||
pmx = DC_pmxWorldToDevice(pdc);
|
||||
break;
|
||||
|
||||
case GdiDeviceSpaceToWorldSpace:
|
||||
pmx = DC_pmxDeviceToWorld(pdc);
|
||||
break;
|
||||
|
||||
case GdiPageSpaceToDeviceSpace:
|
||||
DC_vGetPageToDevice(pdc, &mxPageToDevice);
|
||||
pmx = &mxPageToDevice;
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINT1("Unknown transform %lu\n", iXform);
|
||||
ret = FALSE;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Initialize an XFORMOBJ */
|
||||
XFORMOBJ_vInit(&xo, pmx);
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForWrite(XForm, sizeof(XFORM), 1);
|
||||
switch (iXform)
|
||||
{
|
||||
case GdiWorldSpaceToPageSpace:
|
||||
MatrixS2XForm(XForm, &pdc->dclevel.mxWorldToPage);
|
||||
break;
|
||||
|
||||
case GdiWorldSpaceToDeviceSpace:
|
||||
MatrixS2XForm(XForm, &pdc->dclevel.mxWorldToDevice);
|
||||
break;
|
||||
|
||||
case GdiPageSpaceToDeviceSpace:
|
||||
IntWindowToViewPort(pdc->pdcattr, XForm);
|
||||
break;
|
||||
|
||||
case GdiDeviceSpaceToWorldSpace:
|
||||
MatrixS2XForm(XForm, &pdc->dclevel.mxDeviceToWorld);
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINT1("Unknown transform %lu\n", iXform);
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
ProbeForWrite(pXForm, sizeof(XFORML), 1);
|
||||
XFORMOBJ_iGetXform(&xo, (XFORML*)pXForm);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
ret = FALSE;
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
leave:
|
||||
DC_UnlockDc(pdc);
|
||||
return NT_SUCCESS(Status);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -295,11 +406,11 @@ NtGdiTransformPoints(
|
|||
switch (iMode)
|
||||
{
|
||||
case GdiDpToLp:
|
||||
IntDPtoLP(pdc, Points, Count);
|
||||
DC_vXformDeviceToWorld(pdc, Count, Points, Points);
|
||||
break;
|
||||
|
||||
case GdiLpToDp:
|
||||
IntLPtoDP(pdc, Points, Count);
|
||||
DC_vXformWorldToDevice(pdc, Count, Points, Points);
|
||||
break;
|
||||
|
||||
case 2: // Not supported yet. Need testing.
|
||||
|
@ -331,78 +442,78 @@ leave:
|
|||
return ret;
|
||||
}
|
||||
|
||||
// FIXME: Don't use floating point in the kernel
|
||||
BOOL
|
||||
FASTCALL
|
||||
IntGdiModifyWorldTransform(
|
||||
PDC pDc,
|
||||
CONST LPXFORM lpXForm,
|
||||
DWORD Mode)
|
||||
NTAPI
|
||||
GreModifyWorldTransform(
|
||||
PDC pdc,
|
||||
const XFORML *pxform,
|
||||
DWORD dwMode)
|
||||
{
|
||||
XFORM xformWorld2Wnd;
|
||||
ASSERT(pDc);
|
||||
MATRIX mxSrc;
|
||||
XFORMOBJ xoSrc, xoDC;
|
||||
|
||||
switch (Mode)
|
||||
switch (dwMode)
|
||||
{
|
||||
case MWT_IDENTITY:
|
||||
xformWorld2Wnd.eM11 = 1.0f;
|
||||
xformWorld2Wnd.eM12 = 0.0f;
|
||||
xformWorld2Wnd.eM21 = 0.0f;
|
||||
xformWorld2Wnd.eM22 = 1.0f;
|
||||
xformWorld2Wnd.eDx = 0.0f;
|
||||
xformWorld2Wnd.eDy = 0.0f;
|
||||
XForm2MatrixS(&pDc->dclevel.mxWorldToPage, &xformWorld2Wnd);
|
||||
pdc->pdcattr->mxWorldToPage = gmxIdentity;
|
||||
break;
|
||||
|
||||
case MWT_LEFTMULTIPLY:
|
||||
MatrixS2XForm(&xformWorld2Wnd, &pDc->dclevel.mxWorldToPage);
|
||||
IntGdiCombineTransform(&xformWorld2Wnd, lpXForm, &xformWorld2Wnd);
|
||||
XForm2MatrixS(&pDc->dclevel.mxWorldToPage, &xformWorld2Wnd);
|
||||
XFORMOBJ_vInit(&xoDC, &pdc->pdcattr->mxWorldToPage);
|
||||
XFORMOBJ_vInit(&xoSrc, &mxSrc);
|
||||
XFORMOBJ_iSetXform(&xoSrc, pxform);
|
||||
XFORMOBJ_iCombine(&xoDC, &xoSrc, &xoDC);
|
||||
break;
|
||||
|
||||
case MWT_RIGHTMULTIPLY:
|
||||
MatrixS2XForm(&xformWorld2Wnd, &pDc->dclevel.mxWorldToPage);
|
||||
IntGdiCombineTransform(&xformWorld2Wnd, &xformWorld2Wnd, lpXForm);
|
||||
XForm2MatrixS(&pDc->dclevel.mxWorldToPage, &xformWorld2Wnd);
|
||||
XFORMOBJ_vInit(&xoDC, &pdc->pdcattr->mxWorldToPage);
|
||||
XFORMOBJ_vInit(&xoSrc, &mxSrc);
|
||||
XFORMOBJ_iSetXform(&xoSrc, pxform);
|
||||
XFORMOBJ_iCombine(&xoDC, &xoDC, &xoSrc);
|
||||
break;
|
||||
|
||||
case MWT_MAX+1: // Must be MWT_SET????
|
||||
XForm2MatrixS(&pDc->dclevel.mxWorldToPage, lpXForm); // Do it like Wine.
|
||||
XFORMOBJ_vInit(&xoDC, &pdc->pdcattr->mxWorldToPage);
|
||||
XFORMOBJ_iSetXform(&xoDC, pxform);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
DC_UpdateXforms(pDc);
|
||||
|
||||
/*Set invalidation flags */
|
||||
pdc->pdcattr->flXform |= WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
APIENTRY
|
||||
NtGdiModifyWorldTransform(
|
||||
HDC hDC,
|
||||
LPXFORM UnsafeXForm,
|
||||
DWORD Mode)
|
||||
HDC hdc,
|
||||
LPXFORM pxformUnsafe,
|
||||
DWORD dwMode)
|
||||
{
|
||||
PDC dc;
|
||||
XFORM SafeXForm; // FIXME: Use XFORML
|
||||
PDC pdc;
|
||||
XFORML xformSafe;
|
||||
BOOL Ret = TRUE;
|
||||
|
||||
dc = DC_LockDc(hDC);
|
||||
if (!dc)
|
||||
pdc = DC_LockDc(hdc);
|
||||
if (!pdc)
|
||||
{
|
||||
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// The xform is permitted to be NULL for MWT_IDENTITY.
|
||||
// However, if it is not NULL, then it must be valid even though it is not used.
|
||||
if (UnsafeXForm != NULL || Mode != MWT_IDENTITY)
|
||||
/* The xform is permitted to be NULL for MWT_IDENTITY.
|
||||
* However, if it is not NULL, then it must be valid even
|
||||
* though it is not used. */
|
||||
if (pxformUnsafe != NULL || dwMode != MWT_IDENTITY)
|
||||
{
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForRead(UnsafeXForm, sizeof(XFORM), 1);
|
||||
RtlCopyMemory(&SafeXForm, UnsafeXForm, sizeof(XFORM));
|
||||
ProbeForRead(pxformUnsafe, sizeof(XFORML), 1);
|
||||
RtlCopyMemory(&xformSafe, pxformUnsafe, sizeof(XFORML));
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
|
@ -411,9 +522,9 @@ NtGdiModifyWorldTransform(
|
|||
_SEH2_END;
|
||||
}
|
||||
|
||||
// Safe to handle kernel mode data.
|
||||
if (Ret) Ret = IntGdiModifyWorldTransform(dc, &SafeXForm, Mode);
|
||||
DC_UnlockDc(dc);
|
||||
/* Safe to handle kernel mode data. */
|
||||
if (Ret) Ret = GreModifyWorldTransform(pdc, &xformSafe, dwMode);
|
||||
DC_UnlockDc(pdc);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
|
@ -469,7 +580,8 @@ NtGdiOffsetViewportOrgEx(
|
|||
}
|
||||
pdcattr->ptlViewportOrg.x += XOffset;
|
||||
pdcattr->ptlViewportOrg.y += YOffset;
|
||||
DC_UpdateXforms(dc);
|
||||
pdcattr->flXform |= PAGE_XLATE_CHANGED;
|
||||
|
||||
DC_UnlockDc(dc);
|
||||
|
||||
return TRUE;
|
||||
|
@ -520,8 +632,8 @@ NtGdiOffsetWindowOrgEx(
|
|||
|
||||
pdcattr->ptlWindowOrg.x += XOffset;
|
||||
pdcattr->ptlWindowOrg.y += YOffset;
|
||||
pdcattr->flXform |= PAGE_XLATE_CHANGED;
|
||||
|
||||
DC_UpdateXforms(dc);
|
||||
DC_UnlockDc(dc);
|
||||
|
||||
return TRUE;
|
||||
|
@ -554,6 +666,7 @@ NtGdiScaleViewportExtEx(
|
|||
{
|
||||
if (Xdenom && Ydenom)
|
||||
{
|
||||
DC_pszlViewportExt(pDC);
|
||||
X = Xnum * pdcattr->szlViewportExt.cx / Xdenom;
|
||||
if (X)
|
||||
{
|
||||
|
@ -562,6 +675,7 @@ NtGdiScaleViewportExtEx(
|
|||
{
|
||||
pdcattr->szlViewportExt.cx = X;
|
||||
pdcattr->szlViewportExt.cy = Y;
|
||||
pdcattr->flXform |= PAGE_XLATE_CHANGED;
|
||||
|
||||
IntMirrorWindowOrg(pDC);
|
||||
|
||||
|
@ -571,9 +685,8 @@ NtGdiScaleViewportExtEx(
|
|||
|
||||
if (pdcattr->iMapMode == MM_ISOTROPIC)
|
||||
{
|
||||
IntFixIsotropicMapping(pDC);
|
||||
DC_vFixIsotropicMapping(pDC);
|
||||
}
|
||||
DC_UpdateXforms(pDC);
|
||||
|
||||
Ret = TRUE;
|
||||
}
|
||||
|
@ -671,9 +784,6 @@ NtGdiScaleWindowExtEx(
|
|||
|
||||
pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
|
||||
|
||||
if (pdcattr->iMapMode == MM_ISOTROPIC) IntFixIsotropicMapping(pDC);
|
||||
DC_UpdateXforms(pDC);
|
||||
|
||||
Ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -698,6 +808,9 @@ IntGdiSetMapMode(
|
|||
PrevMapMode = pdcattr->iMapMode;
|
||||
|
||||
pdcattr->iMapMode = MapMode;
|
||||
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);
|
||||
|
||||
switch (MapMode)
|
||||
{
|
||||
|
@ -706,10 +819,7 @@ IntGdiSetMapMode(
|
|||
pdcattr->szlWindowExt.cy = 1;
|
||||
pdcattr->szlViewportExt.cx = 1;
|
||||
pdcattr->szlViewportExt.cy = 1;
|
||||
pdcattr->flXform &= ~(ISO_OR_ANISO_MAP_MODE|PTOD_EFM22_NEGATIVE|
|
||||
PTOD_EFM11_NEGATIVE|POSITIVE_Y_IS_UP);
|
||||
pdcattr->flXform |= (PAGE_XLATE_CHANGED|PAGE_TO_DEVICE_SCALE_IDENTITY|
|
||||
INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
|
||||
pdcattr->flXform |= PAGE_TO_DEVICE_SCALE_IDENTITY;
|
||||
break;
|
||||
|
||||
case MM_ISOTROPIC:
|
||||
|
@ -760,7 +870,9 @@ IntGdiSetMapMode(
|
|||
pdcattr->iMapMode = PrevMapMode;
|
||||
PrevMapMode = 0;
|
||||
}
|
||||
DC_UpdateXforms(dc);
|
||||
|
||||
pdcattr->flXform |= (PAGE_XLATE_CHANGED|PAGE_EXTENTS_CHANGED|
|
||||
INVALIDATE_ATTRIBUTES|DEVICE_TO_PAGE_INVALID|DEVICE_TO_WORLD_INVALID);
|
||||
|
||||
return PrevMapMode;
|
||||
}
|
||||
|
@ -811,8 +923,8 @@ NtGdiSetViewportOrgEx(
|
|||
|
||||
pdcattr->ptlViewportOrg.x = X;
|
||||
pdcattr->ptlViewportOrg.y = Y;
|
||||
pdcattr->flXform |= PAGE_XLATE_CHANGED;
|
||||
|
||||
DC_UpdateXforms(dc);
|
||||
DC_UnlockDc(dc);
|
||||
|
||||
return TRUE;
|
||||
|
@ -863,8 +975,8 @@ NtGdiSetWindowOrgEx(
|
|||
|
||||
pdcattr->ptlWindowOrg.x = X;
|
||||
pdcattr->ptlWindowOrg.y = Y;
|
||||
pdcattr->flXform |= PAGE_XLATE_CHANGED;
|
||||
|
||||
DC_UpdateXforms(dc);
|
||||
DC_UnlockDc(dc);
|
||||
|
||||
return TRUE;
|
||||
|
@ -896,6 +1008,7 @@ IntMirrorWindowOrg(PDC dc)
|
|||
X = (X * pdcattr->szlWindowExt.cx) / pdcattr->szlViewportExt.cx;
|
||||
|
||||
pdcattr->ptlWindowOrg.x = pdcattr->lWindowOrgx - X; // Now set the inverted win origion.
|
||||
pdcattr->flXform |= PAGE_XLATE_CHANGED;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -918,13 +1031,13 @@ DC_vSetLayout(
|
|||
pdcattr->iMapMode = MM_ANISOTROPIC;
|
||||
}
|
||||
|
||||
pdcattr->szlWindowExt.cy = -pdcattr->szlWindowExt.cy;
|
||||
pdcattr->ptlWindowOrg.x = -pdcattr->ptlWindowOrg.x;
|
||||
//pdcattr->szlWindowExt.cy = -pdcattr->szlWindowExt.cy;
|
||||
//pdcattr->ptlWindowOrg.x = -pdcattr->ptlWindowOrg.x;
|
||||
|
||||
if (wox == -1)
|
||||
IntMirrorWindowOrg(pdc);
|
||||
else
|
||||
pdcattr->ptlWindowOrg.x = wox - pdcattr->ptlWindowOrg.x;
|
||||
//if (wox == -1)
|
||||
// IntMirrorWindowOrg(pdc);
|
||||
//else
|
||||
// pdcattr->ptlWindowOrg.x = wox - pdcattr->ptlWindowOrg.x;
|
||||
|
||||
if (!(pdcattr->flTextAlign & TA_CENTER)) pdcattr->flTextAlign |= TA_RIGHT;
|
||||
|
||||
|
@ -956,8 +1069,7 @@ NtGdiSetLayout(
|
|||
IN DWORD dwLayout)
|
||||
{
|
||||
PDC pdc;
|
||||
PDC_ATTR pdcattr;
|
||||
DWORD oLayout;
|
||||
DWORD dwOldLayout;
|
||||
|
||||
pdc = DC_LockDc(hdc);
|
||||
if (!pdc)
|
||||
|
@ -965,13 +1077,12 @@ NtGdiSetLayout(
|
|||
EngSetLastError(ERROR_INVALID_HANDLE);
|
||||
return GDI_ERROR;
|
||||
}
|
||||
pdcattr = pdc->pdcattr;
|
||||
|
||||
oLayout = pdcattr->dwLayout;
|
||||
dwOldLayout = pdc->pdcattr->dwLayout;
|
||||
DC_vSetLayout(pdc, wox, dwLayout);
|
||||
|
||||
DC_UnlockDc(pdc);
|
||||
return oLayout;
|
||||
return dwOldLayout;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1041,7 +1152,6 @@ NtGdiSetSizeDevice(
|
|||
pdcattr->szlVirtualDeviceSize.cx = cxVirtualDevice;
|
||||
pdcattr->szlVirtualDeviceSize.cy = cyVirtualDevice;
|
||||
|
||||
// DC_UpdateXforms(dc);
|
||||
DC_UnlockDc(dc);
|
||||
|
||||
return TRUE;
|
||||
|
@ -1087,51 +1197,19 @@ NtGdiSetVirtualResolution(
|
|||
pdcattr->szlVirtualDeviceMm.cx = cxVirtualDeviceMm;
|
||||
pdcattr->szlVirtualDeviceMm.cy = cyVirtualDeviceMm;
|
||||
|
||||
// DC_UpdateXforms(dc);
|
||||
// DC_vUpdateXforms(dc);
|
||||
DC_UnlockDc(dc);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// FIXME: Don't use floating point in the kernel!
|
||||
BOOL FASTCALL
|
||||
DC_InvertXform(const XFORM *xformSrc,
|
||||
XFORM *xformDest)
|
||||
{
|
||||
FLOAT determinant;
|
||||
|
||||
determinant = xformSrc->eM11*xformSrc->eM22 - xformSrc->eM12*xformSrc->eM21;
|
||||
if (determinant > -1e-12 && determinant < 1e-12)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
xformDest->eM11 = xformSrc->eM22 / determinant;
|
||||
xformDest->eM12 = -xformSrc->eM12 / determinant;
|
||||
xformDest->eM21 = -xformSrc->eM21 / determinant;
|
||||
xformDest->eM22 = xformSrc->eM11 / determinant;
|
||||
xformDest->eDx = -xformSrc->eDx * xformDest->eM11 - xformSrc->eDy * xformDest->eM21;
|
||||
xformDest->eDy = -xformSrc->eDx * xformDest->eM12 - xformSrc->eDy * xformDest->eM22;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LONG FASTCALL
|
||||
IntCalcFillOrigin(PDC pdc)
|
||||
{
|
||||
pdc->ptlFillOrigin.x = pdc->dclevel.ptlBrushOrigin.x + pdc->ptlDCOrig.x;
|
||||
pdc->ptlFillOrigin.y = pdc->dclevel.ptlBrushOrigin.y + pdc->ptlDCOrig.y;
|
||||
|
||||
return pdc->ptlFillOrigin.y;
|
||||
}
|
||||
|
||||
PPOINTL
|
||||
FASTCALL
|
||||
IntptlBrushOrigin(PDC pdc, LONG x, LONG y )
|
||||
{
|
||||
pdc->dclevel.ptlBrushOrigin.x = x;
|
||||
pdc->dclevel.ptlBrushOrigin.y = y;
|
||||
IntCalcFillOrigin(pdc);
|
||||
pdc->ptlFillOrigin.x = pdc->dclevel.ptlBrushOrigin.x + pdc->ptlDCOrig.x;
|
||||
pdc->ptlFillOrigin.y = pdc->dclevel.ptlBrushOrigin.y + pdc->ptlDCOrig.y;
|
||||
return &pdc->dclevel.ptlBrushOrigin;
|
||||
}
|
||||
|
||||
|
@ -1163,6 +1241,7 @@ NtGdiGetDCPoint(
|
|||
DC *pdc;
|
||||
POINTL SafePoint;
|
||||
SIZE Size;
|
||||
PSIZEL pszlViewportExt;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
if (!Point)
|
||||
|
@ -1181,9 +1260,9 @@ NtGdiGetDCPoint(
|
|||
switch (iPoint)
|
||||
{
|
||||
case GdiGetViewPortExt:
|
||||
DC_vUpdateViewportExt(pdc);
|
||||
SafePoint.x = pdc->pdcattr->szlViewportExt.cx;
|
||||
SafePoint.y = pdc->pdcattr->szlViewportExt.cy;
|
||||
pszlViewportExt = DC_pszlViewportExt(pdc);
|
||||
SafePoint.x = pszlViewportExt->cx;
|
||||
SafePoint.y = pszlViewportExt->cy;
|
||||
break;
|
||||
|
||||
case GdiGetWindowExt:
|
||||
|
|
|
@ -17,23 +17,6 @@
|
|||
PSURFACE psurfDefaultBitmap = NULL;
|
||||
PBRUSH pbrDefaultBrush = NULL;
|
||||
|
||||
// FIXME: These should go to floatobj.h or something
|
||||
#ifdef _M_IX86
|
||||
#define FLOATOBJ_0 {0x00000000, 0x00000000}
|
||||
#define FLOATOBJ_1 {0x40000000, 0x00000002}
|
||||
#define FLOATOBJ_16 {0x40000000, 0x00000006}
|
||||
#define FLOATOBJ_1_16 {0x40000000, 0xfffffffe}
|
||||
#else
|
||||
#define FLOATOBJ_0 0.
|
||||
#define FLOATOBJ_1 1.
|
||||
#define FLOATOBJ_16 16.
|
||||
#define FLOATOBJ_1_16 (1./16.)
|
||||
#endif
|
||||
|
||||
static const FLOATOBJ gef0 = FLOATOBJ_0;
|
||||
static const FLOATOBJ gef1 = FLOATOBJ_1;
|
||||
static const FLOATOBJ gef16 = FLOATOBJ_16;
|
||||
|
||||
static const MATRIX gmxWorldToDeviceDefault =
|
||||
{
|
||||
FLOATOBJ_16, FLOATOBJ_0,
|
||||
|
|
|
@ -663,7 +663,7 @@ NtGdiRectangle(HDC hDC,
|
|||
}
|
||||
|
||||
/* Do we rotate or shear? */
|
||||
if (!(dc->dclevel.mxWorldToDevice.flAccel & MX_SCALE))
|
||||
if (!(dc->dclevel.mxWorldToDevice.flAccel & XFORM_SCALE))
|
||||
{
|
||||
POINTL DestCoords[4];
|
||||
ULONG PolyCounts = 4;
|
||||
|
|
|
@ -1424,8 +1424,7 @@ BOOL FASTCALL PATH_StrokePath(DC *dc, PPATH pPath)
|
|||
/* Save the mapping mode info */
|
||||
mapMode = pdcattr->iMapMode;
|
||||
|
||||
DC_vUpdateViewportExt(dc);
|
||||
szViewportExt = dc->pdcattr->szlViewportExt;
|
||||
szViewportExt = *DC_pszlViewportExt(dc);
|
||||
ptViewportOrg = dc->pdcattr->ptlViewportOrg;
|
||||
szWindowExt = dc->pdcattr->szlWindowExt;
|
||||
ptWindowOrg = dc->pdcattr->ptlWindowOrg;
|
||||
|
@ -1440,7 +1439,7 @@ BOOL FASTCALL PATH_StrokePath(DC *dc, PPATH pPath)
|
|||
pdcattr->ptlWindowOrg.y = 0;
|
||||
graphicsMode = pdcattr->iGraphicsMode;
|
||||
pdcattr->iGraphicsMode = GM_ADVANCED;
|
||||
IntGdiModifyWorldTransform(dc, &xform, MWT_IDENTITY);
|
||||
GreModifyWorldTransform(dc, (XFORML*)&xform, MWT_IDENTITY);
|
||||
pdcattr->iGraphicsMode = graphicsMode;
|
||||
|
||||
/* Allocate enough memory for the worst case without beziers (one PT_MOVETO
|
||||
|
|
|
@ -95,13 +95,13 @@ FORCEINLINE
|
|||
ULONG
|
||||
HintFromAccel(ULONG flAccel)
|
||||
{
|
||||
switch (flAccel & (MX_NOTRANSLATE | MX_IDENTITYSCALE | MX_SCALE))
|
||||
switch (flAccel & (XFORM_SCALE|XFORM_UNITY|XFORM_NO_TRANSLATION))
|
||||
{
|
||||
case (MX_SCALE | MX_IDENTITYSCALE | MX_NOTRANSLATE):
|
||||
case (XFORM_SCALE|XFORM_UNITY|XFORM_NO_TRANSLATION):
|
||||
return GX_IDENTITY;
|
||||
case (MX_SCALE | MX_IDENTITYSCALE):
|
||||
case (XFORM_SCALE|XFORM_UNITY):
|
||||
return GX_OFFSET;
|
||||
case MX_SCALE:
|
||||
case XFORM_SCALE:
|
||||
return GX_SCALE;
|
||||
default:
|
||||
return GX_GENERAL;
|
||||
|
@ -126,25 +126,25 @@ XFORMOBJ_UpdateAccel(
|
|||
if (FLOATOBJ_Equal0(&pmx->efDx) &&
|
||||
FLOATOBJ_Equal0(&pmx->efDy))
|
||||
{
|
||||
pmx->flAccel |= MX_NOTRANSLATE;
|
||||
pmx->flAccel |= XFORM_NO_TRANSLATION;
|
||||
}
|
||||
|
||||
if (FLOATOBJ_Equal0(&pmx->efM12) &&
|
||||
FLOATOBJ_Equal0(&pmx->efM21))
|
||||
{
|
||||
pmx->flAccel |= MX_SCALE;
|
||||
pmx->flAccel |= XFORM_SCALE;
|
||||
}
|
||||
|
||||
if (FLOATOBJ_Equal1(&pmx->efM11) &&
|
||||
FLOATOBJ_Equal1(&pmx->efM22))
|
||||
{
|
||||
pmx->flAccel |= MX_IDENTITYSCALE;
|
||||
pmx->flAccel |= XFORM_UNITY;
|
||||
}
|
||||
|
||||
if (FLOATOBJ_IsLong(&pmx->efM11) && FLOATOBJ_IsLong(&pmx->efM12) &&
|
||||
FLOATOBJ_IsLong(&pmx->efM21) && FLOATOBJ_IsLong(&pmx->efM22))
|
||||
{
|
||||
pmx->flAccel |= MX_INTEGER;
|
||||
pmx->flAccel |= XFORM_INTEGER;
|
||||
}
|
||||
|
||||
return HintFromAccel(pmx->flAccel);
|
||||
|
@ -253,10 +253,18 @@ XFORMOBJ_iInverse(
|
|||
{
|
||||
PMATRIX pmxDst, pmxSrc;
|
||||
FLOATOBJ foDet;
|
||||
XFORM xformSrc;
|
||||
union
|
||||
{
|
||||
FLOAT Float;
|
||||
LONG Long;
|
||||
} eDet;
|
||||
|
||||
pmxDst = XFORMOBJ_pmx(pxoDst);
|
||||
pmxSrc = XFORMOBJ_pmx(pxoSrc);
|
||||
|
||||
XFORMOBJ_iGetXform(pxoSrc, (XFORML*)&xformSrc);
|
||||
|
||||
/* det = M11 * M22 - M12 * M21 */
|
||||
MulSub(&foDet, &pmxSrc->efM11, &pmxSrc->efM22, &pmxSrc->efM12, &pmxSrc->efM21);
|
||||
|
||||
|
@ -266,6 +274,8 @@ XFORMOBJ_iInverse(
|
|||
return DDI_ERROR;
|
||||
}
|
||||
|
||||
eDet.Long = FLOATOBJ_GetFloat(&foDet);
|
||||
|
||||
/* Calculate adj(A) / det(A) */
|
||||
pmxDst->efM11 = pmxSrc->efM22;
|
||||
FLOATOBJ_Div(&pmxDst->efM11, &foDet);
|
||||
|
@ -274,10 +284,10 @@ XFORMOBJ_iInverse(
|
|||
|
||||
/* The other 2 are negative, negate foDet for that */
|
||||
FLOATOBJ_Neg(&foDet);
|
||||
pmxDst->efM12 = pmxSrc->efM21;
|
||||
pmxDst->efM12 = pmxSrc->efM12;
|
||||
FLOATOBJ_Div(&pmxDst->efM12, &foDet);
|
||||
pmxDst->efM21 = pmxSrc->efM12;
|
||||
FLOATOBJ_Div(&pmxDst->efM22, &foDet);
|
||||
pmxDst->efM21 = pmxSrc->efM21;
|
||||
FLOATOBJ_Div(&pmxDst->efM21, &foDet);
|
||||
|
||||
/* Update accelerators and return complexity */
|
||||
return XFORMOBJ_UpdateAccel(pxoDst);
|
||||
|
@ -300,13 +310,13 @@ XFORMOBJ_bXformFixPoints(
|
|||
pmx = XFORMOBJ_pmx(pxo);
|
||||
flAccel = pmx->flAccel;
|
||||
|
||||
if ((flAccel & (MX_SCALE|MX_IDENTITYSCALE)) == (MX_SCALE|MX_IDENTITYSCALE))
|
||||
if ((flAccel & (XFORM_SCALE|XFORM_UNITY)) == (XFORM_SCALE|XFORM_UNITY))
|
||||
{
|
||||
/* Identity transformation, nothing todo */
|
||||
}
|
||||
else if (flAccel & MX_INTEGER)
|
||||
else if (flAccel & XFORM_INTEGER)
|
||||
{
|
||||
if (flAccel & MX_IDENTITYSCALE)
|
||||
if (flAccel & XFORM_UNITY)
|
||||
{
|
||||
/* 1-scale integer transform */
|
||||
i = cPoints - 1;
|
||||
|
@ -319,7 +329,7 @@ XFORMOBJ_bXformFixPoints(
|
|||
}
|
||||
while (--i >= 0);
|
||||
}
|
||||
else if (flAccel & MX_SCALE)
|
||||
else if (flAccel & XFORM_SCALE)
|
||||
{
|
||||
/* Diagonal integer transform */
|
||||
i = cPoints - 1;
|
||||
|
@ -346,7 +356,7 @@ XFORMOBJ_bXformFixPoints(
|
|||
while (--i >= 0);
|
||||
}
|
||||
}
|
||||
else if (flAccel & MX_IDENTITYSCALE)
|
||||
else if (flAccel & XFORM_UNITY)
|
||||
{
|
||||
/* 1-scale transform */
|
||||
i = cPoints - 1;
|
||||
|
@ -361,7 +371,7 @@ XFORMOBJ_bXformFixPoints(
|
|||
}
|
||||
while (--i >= 0);
|
||||
}
|
||||
else if (flAccel & MX_SCALE)
|
||||
else if (flAccel & XFORM_SCALE)
|
||||
{
|
||||
/* Diagonal float transform */
|
||||
i = cPoints - 1;
|
||||
|
@ -390,13 +400,12 @@ XFORMOBJ_bXformFixPoints(
|
|||
while (--i >= 0);
|
||||
}
|
||||
|
||||
if (!(pmx->flAccel & MX_NOTRANSLATE))
|
||||
if (!(pmx->flAccel & XFORM_NO_TRANSLATION))
|
||||
{
|
||||
/* Translate points */
|
||||
i = cPoints - 1;
|
||||
do
|
||||
{
|
||||
// DPRINT1("Translating Points (%d,%d)->(%d,%d)\n", pptOut[i].x, pptOut[i].y, pptOut[i].x + pmx->fxDx, pptOut[i].y + pmx->fxDy);
|
||||
pptOut[i].x += pmx->fxDx;
|
||||
pptOut[i].y += pmx->fxDy;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue