/**************************************************************************\ * * Copyright (c) 1998 Microsoft Corporation * * Abstract: * * Contains simple engine-wide prototypes and helper functions and * compile time flags. * * History: * * 12/04/1998 davidx * Created it. * \**************************************************************************/ #ifndef _ENGINE_HPP #define _ENGINE_HPP //-------------------------------------------------------------------------- // GDI+ internal prototypes //-------------------------------------------------------------------------- class GpDevice; struct DpPen; USHORT GetLanguageID(); BOOL InitSystemFontsDirs(VOID); //WCHAR **system_dir, WCHAR **fonts_dir); UINT32 Crc32( IN const VOID* buf, IN UINT size, IN UINT32 checksum ); // Get the ceiling the same way the rasterizer does inline INT RasterizerCeiling( REAL value ) { return GpFix4Ceiling(GpRealToFix4(value)); } GpStatus BoundsFToRect( const GpRectF *rectF, GpRect * rect ); /* REAL GetPenDelta( const DpPen* pen, const GpMatrix* matrix, REAL dpiX, REAL dpiY ); */ REAL GetDeviceWidth( REAL width, GpUnit unit, REAL dpi); VOID TransformBounds( const GpMatrix *matrix, REAL x0, REAL y0, REAL x1, REAL y1, GpRectF *bounds ); LONG WINAPI InterlockedCompareExchangeWin95( IN OUT PLONG destination, IN LONG exchange, IN LONG comperand ); LONG WINAPI InterlockedIncrementWin95( IN LPLONG lpAddend ); LONG WINAPI InterlockedDecrementWin95( IN LPLONG lpAddend ); BOOL APIENTRY GdiIsMetaPrintDCWin9x( HDC hdc ); //-------------------------------------------------------------------------- // The following macro is useful for checking if the creation of an // internal object succeeds. // // We don't want to use exceptions to allow a constructor to indicate failure, // so the object has to contain an 'IsValid()' member that returns TRUE if // the object was successfully allocated. But then the caller has to write // the following code: // // p = new Object(); // if (!p || !p->IsValid()) // { // delete p; // ... // // The following macro can be used to replace this with: // // p = new Object(); // if (!CheckValid(p)) // { // ... // // !!! // Note that CheckValid sets the input parameter to NULL // when the return value is FALSE. // //-------------------------------------------------------------------------- template inline BOOL CheckValid( T*& p ) { if (p && p->IsValid()) { return TRUE; } else { delete p; p = NULL; return FALSE; } } //-------------------------------------------------------------------------- // Name dynamic array types //-------------------------------------------------------------------------- typedef DynArray DynPointFArray; typedef DynArray DynPointArray; typedef DynArray DynByteArray; typedef DynArray DynIntArray; typedef DynArray DynRealArray; typedef DynArray DynPointerArray; //-------------------------------------------------------------------------- // Raw critical section object // The Initialize function can throw. //-------------------------------------------------------------------------- class GpSemaphore { private: CRITICAL_SECTION CriticalSection; BOOL Initialized; public: GpSemaphore() { Initialized = FALSE; } VOID Initialize( VOID ) { if (!Initialized) { // The caller has to have a Try_Except around us. __try { InitializeCriticalSection(&CriticalSection); } __except(EXCEPTION_CONTINUE_SEARCH) { } Initialized = TRUE; } } VOID Uninitialize( VOID ); VOID Lock( VOID ) { ASSERT(Initialized); EnterCriticalSection(&CriticalSection); } VOID Unlock( VOID ) { ASSERT(Initialized); LeaveCriticalSection(&CriticalSection); } BOOL IsLocked( VOID ); BOOL IsLockedByCurrentThread( VOID ); }; //------------------------------------------------------------------------ // FillMemoryInt32 - Fill an INT32 array with the specified value // CopyMemoryInt32 - Copy INT32 values from one array to another //------------------------------------------------------------------------ inline VOID FillMemoryInt32( VOID* buf, INT count, INT32 val ) { INT32* p = (INT32*) buf; while (count-- > 0) *p++ = val; } inline VOID CopyMemoryInt32( VOID* dst, const VOID* src, INT count ) { INT32* d = (INT32*) dst; const INT32* s = (const INT32*) src; while (count-- > 0) *d++ = *s++; } //------------------------------------------------------------------------ // CompareExchangeLong_Ptr - Perform an interlocked compare-exchange // on a LONG_PTR. Unfortunately, Win95 does not export // InterlockedCompareExchange, so on that platform we have // to create our own. But on NT, we CANNOT roll our own, because // of MP and NT64 issues. // // This method should be called instead of calling through the // Globals::InterlockedCompareExchangeFunction directly, because // on Alpha machines, Globals::InterlockedCompareExchangeFunction does // NOT get initialized. //------------------------------------------------------------------------ inline LONG_PTR CompareExchangeLong_Ptr( LONG_PTR *destination, LONG_PTR exchange, LONG_PTR comperand ) { #if defined(_X86_) return InterlockedCompareExchange(destination, exchange, comperand); #else return (LONG_PTR)InterlockedCompareExchangePointer( (PVOID *)destination, (PVOID)exchange, (PVOID)comperand); #endif } //------------------------------------------------------------------------ // CompareExchangePointer - Perform an interlocked compare-exchange // on a pointer. Unfortunately, Win95 does not export // InterlockedCompareExchangePointer, so on that platform we have // to create our own. But on NT, we CANNOT roll our own, because // of MP and NT64 issues. //------------------------------------------------------------------------ inline VOID* CompareExchangePointer( VOID** destination, VOID* exchange, VOID* comperand ) { #if defined(_X86_) return((VOID*) InterlockedCompareExchange((LONG*) destination, (LONG) exchange, (LONG) comperand)); #else return(InterlockedCompareExchangePointer(destination, exchange, comperand)); #endif } //-------------------------------------------------------------------------- // This routine retrieves a quick, pre-allocated region from a one-deep // cache. Note that the contents will be random. This call is intended // largely for GDI API calls such as GetRandomRgn that require a pre-created // region. // // NOTE: This can return a NULL region handle. //-------------------------------------------------------------------------- inline HRGN GetCachedGdiRegion( VOID ) { HRGN regionHandle = Globals::CachedGdiRegion; // If the Globals::CachedGdiRegion is NULL, that means that someone // else has the cached region, so we create a new one. // It is possible during multi thread access for us to create a region // when it's not strictly necessary --- i.e. a thread releases the cached // region when this thread is between the above assignment and the next // if statement, but that's only non-optimal and we'll work correctly // under those circumstances. if ((regionHandle == NULL) || (CompareExchangePointer( (VOID**) &Globals::CachedGdiRegion, NULL, (VOID*) regionHandle) != regionHandle ) ) { regionHandle = CreateRectRgn(0, 0, 1, 1); } return(regionHandle); } //-------------------------------------------------------------------------- // This routine releases a region to the one-deep cache. //-------------------------------------------------------------------------- inline VOID ReleaseCachedGdiRegion( HRGN regionHandle ) { // Note that 'regionHandle' may be NULL at this point if the // CreateRectRgn failed, but that's okay: if (CompareExchangePointer((VOID**) &Globals::CachedGdiRegion, (VOID*) regionHandle, NULL) != NULL) { DeleteObject(regionHandle); } } inline HDC GetCleanHdc( HWND hwnd ) { // Use GetDCEx(DCX_CACHE) to get a nice clean DC (not a CS_OWNDC). // Note that with GetDCEx we have to explicitly respect the window's // clipping styles. We stole this little bit of logic straight from // ntuser\kernel\dc.c for the DCX_USESTYLE case: DWORD getDcFlags = DCX_CACHE; LONG classStyle = GetClassLongA(hwnd, GCL_STYLE); LONG windowStyle = GetWindowLongA(hwnd, GWL_STYLE); if (classStyle & CS_PARENTDC) getDcFlags |= DCX_PARENTCLIP; if (windowStyle & WS_CLIPCHILDREN) getDcFlags |= DCX_CLIPCHILDREN; if (windowStyle & WS_CLIPSIBLINGS) getDcFlags |= DCX_CLIPSIBLINGS; // Minimized windows never exclude their children. if (windowStyle & WS_MINIMIZE) getDcFlags &= ~DCX_CLIPCHILDREN; return GetDCEx(hwnd, NULL, getDcFlags); } inline INT GetIntDistance( POINT & p1, POINT & p2 ) { double dx = (double)(p2.x - p1.x); double dy = (double)(p2.y - p1.y); REAL distance = (REAL)sqrt((dx * dx) + (dy * dy)); return GpRound(distance); } inline REAL GetDistance( GpPointF & p1, GpPointF & p2 ) { double dx = (double)p2.X - p1.X; double dy = (double)p2.Y - p1.Y; return (REAL)sqrt((dx * dx) + (dy * dy)); } inline REAL GetDegreesFromRadians(double radians) { return (REAL)(radians*180.0/3.1415926535897932); } // return angle in degrees from 2 points inline REAL GetAngleFromPoints( const GpPointF & p1, const GpPointF & p2 ) { // Compute the angle of the line formed by p1 and p2. // Note atan2 is only undefined if dP.Y == 0.0 and dP.X == 0.0 // and then it returns 0 radians. // Also, atan2 correctly computes the quadrant from the two input points. GpPointF dP = p2 - p1; double radians = atan2((double)(dP.Y), (double)(dP.X)); return GetDegreesFromRadians(radians); } #define DEFAULT_RESOLUTION 96 // most display screens are set to 96 dpi //-------------------------------------------------------------------------- // The following 3 functions should be used in place of GetObjectType due // to a bug on Windows 9x where an OBJ_METAFILE and another type of object // may share the same handle! // // GetObjectTypeInternal: Call this to determine any object type except // when expecting OBJ_METAFILE or OBJ_*DC. // // GetDCType: Use this when the object should be a DC,and just the type of // DC is required. // // IsValidMetaFile: OBJ_METAFILE is the special case. Use this function to // validate when OBJ_METAFILE is expected. This only means // there is a metafile with this handle. There could also // be an "aliased" object which the caller intended to be // used, so this should not be used to handle multiple // object types. //-------------------------------------------------------------------------- DWORD GetObjectTypeInternal( IN HGDIOBJ handle ); DWORD GetDCType( IN HDC hdc ); inline BOOL IsValidMetaFile( HMETAFILE handle ) { return (GetObjectType(handle) == OBJ_METAFILE); }; #endif // !_ENGINE_HPP