diff --git a/reactos/dll/win32/gdi32/gdi32.rbuild b/reactos/dll/win32/gdi32/gdi32.rbuild index 063b53221d8..b8bfbbc0d21 100644 --- a/reactos/dll/win32/gdi32/gdi32.rbuild +++ b/reactos/dll/win32/gdi32/gdi32.rbuild @@ -31,6 +31,9 @@ brush.c coord.c dc.c + + efloat.c + eng.c enhmfile.c font.c diff --git a/reactos/dll/win32/gdi32/gdi32.spec b/reactos/dll/win32/gdi32/gdi32.spec index de8c127ae4d..60f819a8b65 100644 --- a/reactos/dll/win32/gdi32/gdi32.spec +++ b/reactos/dll/win32/gdi32/gdi32.spec @@ -32,7 +32,7 @@ @ stdcall ColorCorrectPalette(ptr ptr long long) @ stdcall ColorMatchToTarget(ptr ptr long) @ stdcall CombineRgn(long long long long) -@ stdcall CombineTransform(ptr ptr ptr) NtGdiCombineTransform +@ stdcall CombineTransform(ptr ptr ptr) @ stdcall CopyEnhMetaFileA(long str) @ stdcall CopyEnhMetaFileW(long wstr) @ stdcall CopyMetaFileA(long str) @@ -285,7 +285,7 @@ @ stdcall GdiEntry9(ptr ptr ptr ptr ptr ptr) @ stdcall GdiFixUpHandle(ptr) @ stdcall GdiFlush() -@ stdcall GdiFullscreenControl(ptr ptr long ptr ptr) NtGdiFullscreenControl +@ stdcall GdiFullscreenControl(ptr ptr long ptr ptr) NtGdiFullscreenControl @ stdcall GdiGetBatchLimit() @ stdcall GdiGetBitmapBitsSize(ptr) @ stdcall GdiGetCharDimensions(long ptr ptr) @@ -299,7 +299,7 @@ @ stdcall GdiGetPageHandle(ptr long ptr) @ stdcall GdiGetSpoolFileHandle(wstr ptr wstr) @ stdcall GdiGetSpoolMessage(ptr long ptr long) NtGdiGetSpoolMessage -@ stdcall GdiGradientFill(long ptr long ptr long long) +@ stdcall GdiGradientFill(long ptr long ptr long long) @ stdcall GdiInitSpool() NtGdiInitSpool @ stdcall GdiInitializeLanguagePack(long) @ stdcall GdiIsMetaFileDC(long) diff --git a/reactos/dll/win32/gdi32/include/gdi32p.h b/reactos/dll/win32/gdi32/include/gdi32p.h index 0899dcfe514..6fa4a1d2b3a 100644 --- a/reactos/dll/win32/gdi32/include/gdi32p.h +++ b/reactos/dll/win32/gdi32/include/gdi32p.h @@ -292,7 +292,6 @@ int FASTCALL DocumentEventEx(PVOID,HANDLE,HDC,int,ULONG,PVOID,ULONG,PVOID); BOOL FASTCALL EndPagePrinterEx(PVOID,HANDLE); BOOL FASTCALL LoadTheSpoolerDrv(VOID); - FORCEINLINE PVOID GdiAllocBatchCommand( @@ -389,4 +388,33 @@ GdiGetDcAttr(HDC hdc) return pdcattr; } +#ifdef _M_IX86 +FLOATL FASTCALL EFtoF(EFLOAT_S * efp); +#define FOtoF(pfo) EFtoF((EFLOAT_S*)pfo) +#else +#define FOtoF(pfo) (*(pfo)) +#endif + +/* This is an inlined version of lrintf. */ +FORCEINLINE +int +_lrintf(float f) +{ +#if defined(_M_IX86) && defined(__GNUC__) + int ret; + __asm__ __volatile__ ("fistpl %0" : "=m" (ret) : "t" (f) : "st"); + return ret; +#elif defined(_M_IX86) && defined(_MSC_VER) + int ret; + __asm + { + fld f; + fistp ret; + } +#else + /* slow, but portable */ + return (int)floor(x >= 0 ? x+0.5 : x-0.5); +#endif +} + /* EOF */ diff --git a/reactos/dll/win32/gdi32/objects/coord.c b/reactos/dll/win32/gdi32/objects/coord.c index 9f89ae1c89a..fefcda578d9 100644 --- a/reactos/dll/win32/gdi32/objects/coord.c +++ b/reactos/dll/win32/gdi32/objects/coord.c @@ -1,145 +1,152 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS System Libraries + * FILE: dll/gdi32/objects/coord.c + * PURPOSE: Functions for coordinate transformation + * PROGRAMMER: + */ #include "precomp.h" -/* the following deal with IEEE single-precision numbers */ -#define EXCESS 126L -#define SIGNBIT 0x80000000L -#define SIGN(fp) ((fp) & SIGNBIT) -#define EXP(fp) (((fp) >> 23L) & 0xFF) -#define MANT(fp) ((fp) & 0x7FFFFFL) -#define PACK(s,e,m) ((s) | ((e) << 23L) | (m)) - -// Sames as lrintf. -#ifdef __GNUC__ -#define FLOAT_TO_INT(in,out) \ - __asm__ __volatile__ ("fistpl %0" : "=m" (out) : "t" (in) : "st"); -#else -#define FLOAT_TO_INT(in,out) \ - __asm fld in; \ - __asm fistp out; -#endif - -LONG -FASTCALL -EFtoF( EFLOAT_S * efp) +/* Currently we use a MATRIX inside the DC_ATTR containing the + coordinate transformations, while we deal with XFORM structures + internally. If we move all coordinate transformation to gdi32, + we might as well have an XFORM structure in the DC_ATTR. */ +void +MatrixToXForm(XFORM *pxform, const MATRIX *pmx) { - long Mant, Exp, Sign = 0; - - if (!efp->lMant) return 0; - - Mant = efp->lMant; - Exp = efp->lExp; - Sign = SIGN(Mant); - -//// M$ storage emulation - if( Sign ) Mant = -Mant; - Mant = ((Mant & 0x3fffffff) >> 7); - Exp += (EXCESS-1); -//// - Mant = MANT(Mant); - return PACK(Sign, Exp, Mant); + XFORML *pxforml = (XFORML*)pxform; + pxforml->eM11 = FOtoF(&pmx->efM11); + pxforml->eM12 = FOtoF(&pmx->efM12); + pxforml->eM21 = FOtoF(&pmx->efM21); + pxforml->eM22 = FOtoF(&pmx->efM22); + pxforml->eDx = FOtoF(&pmx->efDx); + pxforml->eDy = FOtoF(&pmx->efDy); } -VOID -FASTCALL -FtoEF( EFLOAT_S * efp, FLOATL f) -{ - long Mant, Exp, Sign = 0; - gxf_long worker; - -#ifdef _X86_ - worker.l = f; // It's a float stored in a long. -#else - worker.f = f; -#endif - - Exp = EXP(worker.l); - Mant = MANT(worker.l); - if (SIGN(worker.l)) Sign = -1; -//// M$ storage emulation - Mant = ((Mant << 7) | 0x40000000); - Mant ^= Sign; - Mant -= Sign; - Exp -= (EXCESS-1); -//// - efp->lMant = Mant; - efp->lExp = Exp; -} - - -VOID FASTCALL -CoordCnvP(MATRIX_S * mx, LPPOINT Point) +void +GdiTransformPoints2( + XFORM *pxform, + PPOINT pptOut, + PPOINT pptIn, + ULONG nCount) { + ULONG i; FLOAT x, y; - gxf_long a, b, c; - x = (FLOAT)Point->x; - y = (FLOAT)Point->y; - - a.l = EFtoF( &mx->efM11 ); - b.l = EFtoF( &mx->efM21 ); - c.l = EFtoF( &mx->efDx ); - x = x * a.f + y * b.f + c.f; - - a.l = EFtoF( &mx->efM12 ); - b.l = EFtoF( &mx->efM22 ); - c.l = EFtoF( &mx->efDy ); - y = x * a.f + y * b.f + c.f; - - FLOAT_TO_INT(x, Point->x ); - FLOAT_TO_INT(y, Point->y ); + for (i = 0; i < nCount; i++) + { + x = pptIn[i].x * pxform->eM11 + pptIn[i].y * pxform->eM12 + pxform->eDx; + pptOut[i].x = _lrintf(x); + y = pptIn[i].x * pxform->eM21 + pptIn[i].y * pxform->eM22 + pxform->eDy; + pptOut[i].y = _lrintf(y); + } } +FORCEINLINE +void +GdiTransformPoints( + MATRIX *pmx, + PPOINT pptOut, + PPOINT pptIn, + ULONG nCount) +{ + XFORM xform; + + MatrixToXForm(&xform, pmx); + GdiTransformPoints2(&xform, pptOut, pptIn, nCount); +} + +#define MAX_OFFSET 4294967040.0 BOOL WINAPI -DPtoLP ( HDC hDC, LPPOINT Points, INT Count ) +CombineTransform( + LPXFORM pxfResult, + const XFORM *pxf1, + const XFORM *pxf2) { -#if 0 - INT i; - PDC_ATTR Dc_Attr; + XFORM xformTmp; - if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return FALSE; + /* Do matrix multiplication */ + xformTmp.eM11 = pxf1->eM11 * pxf2->eM11 + pxf1->eM12 * pxf2->eM21; + xformTmp.eM12 = pxf1->eM11 * pxf2->eM12 + pxf1->eM12 * pxf2->eM22; + xformTmp.eM21 = pxf1->eM21 * pxf2->eM11 + pxf1->eM22 * pxf2->eM21; + xformTmp.eM22 = pxf1->eM21 * pxf2->eM12 + pxf1->eM22 * pxf2->eM22; + xformTmp.eDx = pxf1->eDx * pxf2->eM11 + pxf1->eDy * pxf2->eM21 + pxf2->eDx; + xformTmp.eDy = pxf1->eDx * pxf2->eM12 + pxf1->eDy * pxf2->eM22 + pxf2->eDy; - if (Dc_Attr->flXform & ( DEVICE_TO_WORLD_INVALID | // Force a full recalibration! - PAGE_XLATE_CHANGED | // Changes or Updates have been made, - PAGE_EXTENTS_CHANGED | // do processing in kernel space. - WORLD_XFORM_CHANGED )) -#endif - return NtGdiTransformPoints( hDC, Points, Points, Count, GdiDpToLp); // DPtoLP mode. + *pxfResult = xformTmp; #if 0 - else + /* windows compatibility fixups (needs more work) */ + if (_isnan(xformTmp.eM12)) { - for ( i = 0; i < Count; i++ ) - CoordCnvP ( &Dc_Attr->mxDeviceToWorld, &Points[i] ); + if (pxf1->eM11 == 0 || pxf2->eM12 == 0) pxfResult->eM12 = 0.; } - return TRUE; #endif -} + /* Check for invalid offset ranges */ + if (xformTmp.eDx > MAX_OFFSET || xformTmp.eDx < -MAX_OFFSET || + xformTmp.eDy > MAX_OFFSET || xformTmp.eDy < -MAX_OFFSET) + { + return FALSE; + } + return TRUE; +} BOOL WINAPI -LPtoDP ( HDC hDC, LPPOINT Points, INT Count ) +DPtoLP(HDC hdc, LPPOINT lpPoints, INT nCount) { #if 0 INT i; - PDC_ATTR Dc_Attr; + PDC_ATTR pdcattr; - if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return FALSE; - - if (Dc_Attr->flXform & ( PAGE_XLATE_CHANGED | // Check for Changes and Updates - PAGE_EXTENTS_CHANGED | - WORLD_XFORM_CHANGED )) -#endif - return NtGdiTransformPoints( hDC, Points, Points, Count, GdiLpToDp); // LPtoDP mode -#if 0 - else + pdcattr = GdiGetDcAttr(hdc); + if (!pdcattr) { - for ( i = 0; i < Count; i++ ) - CoordCnvP ( &Dc_Attr->mxWorldToDevice, &Points[i] ); + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; } + + if (pdcattr->flXform & ANY_XFORM_CHANGES) + { + GdiFixupTransforms(pdcattr); + } + + // FIXME: can this fail on Windows? + GdiTransformPoints(&pdcattr->mxDeviceToWorld, lpPoints, lpPoints, nCount); + return TRUE; #endif + return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiDpToLp); +} + +BOOL +WINAPI +LPtoDP(HDC hdc, LPPOINT lpPoints, INT nCount) +{ +#if 0 + INT i; + PDC_ATTR pdcattr; + + pdcattr = GdiGetDcAttr(hdc); + if (!pdcattr) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (pdcattr->flXform & ANY_XFORM_CHANGES) + { + GdiFixupTransforms(pdcattr); + } + + // FIXME: can this fail on Windows? + GdiTransformPoints(&pdcattr->mxWorldToDevice, lpPoints, lpPoints, nCount); + + return TRUE; +#endif + return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiLpToDp); } /* @@ -185,9 +192,26 @@ GetCurrentPositionEx(HDC hdc, */ BOOL WINAPI -GetWorldTransform( HDC hDC, LPXFORM lpXform ) +GetWorldTransform(HDC hDC, LPXFORM lpXform) { - return NtGdiGetTransform( hDC, GdiWorldSpaceToPageSpace, lpXform); +#if 0 + PDC_ATTR pdcattr; + + pdcattr = GdiGetDcAttr(hdc); + if (!pdcattr) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (pdcattr->flXform & ANY_XFORM_INVALID) + { + GdiFixupTransforms(pdcattr); + } + + MatrixToXForm(lpXform, &pdcattr->mxWorldToDevice); +#endif + return NtGdiGetTransform(hDC, GdiWorldSpaceToPageSpace, lpXform); } diff --git a/reactos/dll/win32/gdi32/objects/efloat.c b/reactos/dll/win32/gdi32/objects/efloat.c new file mode 100644 index 00000000000..001472e76f6 --- /dev/null +++ b/reactos/dll/win32/gdi32/objects/efloat.c @@ -0,0 +1,62 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS System Libraries + * FILE: dll/gdi32/objects/coord.c + * PURPOSE: Functions to convert between FLOAT and EFLOAT + * PROGRAMMER: James Tabor + */ +#include "precomp.h" + +/* the following deal with IEEE single-precision numbers */ +#define EXCESS 126L +#define SIGNBIT 0x80000000L +#define SIGN(fp) ((fp) & SIGNBIT) +#define EXP(fp) (((fp) >> 23L) & 0xFF) +#define MANT(fp) ((fp) & 0x7FFFFFL) +#define PACK(s,e,m) ((s) | ((e) << 23L) | (m)) + +FLOATL +FASTCALL +EFtoF(EFLOAT_S * efp) +{ + ULONG Mant, Exp, Sign; + + if (!efp->lMant) return 0; + + Mant = efp->lMant; + Exp = efp->lExp; + Sign = SIGN(Mant); + + if (Sign) Mant = -Mant; + Mant >>= 7; + Exp += (EXCESS-1); + + Mant = MANT(Mant); + return PACK(Sign, Exp, Mant); +} + +VOID +FASTCALL +FtoEF( EFLOAT_S * efp, FLOATL f) +{ + ULONG Mant, Exp, Sign = 0; + gxf_long worker; + +#ifdef _X86_ + worker.l = f; // It's a float stored in a long. +#else + worker.f = f; +#endif + + Exp = EXP(worker.l); + Mant = MANT(worker.l); + if (SIGN(worker.l)) Sign = -1; + + Mant = ((Mant << 7) | 0x40000000); + Mant ^= Sign; + Mant -= Sign; + Exp -= (EXCESS-1); + + efp->lMant = Mant; + efp->lExp = Exp; +}