home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************
- * DXHelper.h *
- *------------*
- * Description:
- * This is the header file for core helper functions implementation.
- *-------------------------------------------------------------------------------
- * Created By: Edward W. Connell Date: 07/11/95
- * Copyright (C) 1995 Microsoft Corporation
- * All Rights Reserved
- *
- *-------------------------------------------------------------------------------
- * Revisions:
- *
- *******************************************************************************/
- #ifndef DXHelper_h
- #pragma option push -b -a8 -pc -A- /*P_O_Push*/
- #define DXHelper_h
-
- #ifndef DXTError_h
- #include <DXTError.h>
- #endif
-
- #ifndef DXBounds_h
- #include <DXBounds.h>
- #endif
-
- #ifndef __DXTrans_h__
- #include <DXTrans.h>
- #endif
-
- #ifndef _INC_LIMITS
- #include <limits.h>
- #endif
-
- #ifndef _INC_CRTDBG
- #include <crtdbg.h>
- #endif
-
- #ifndef _INC_MALLOC
- #include <malloc.h>
- #endif
-
- //=== Constants ==============================================================
-
- #define DX_MMX_COUNT_CUTOFF 16
-
- //=== Class, Enum, Struct and Union Declarations =============================
-
- /*** DXLIMAPINFO
- * This structure is used by the array linear interpolation and image
- * filtering routines.
- */
- typedef struct DXLIMAPINFO
- {
- float IndexFrac;
- USHORT Index;
- BYTE Weight;
- } DXLIMAPINFO;
-
- //
- // Declare this class as a global to use for determining when to call MMX optimized
- // code. You can use MinMMXOverCount to determine if MMX instructions are present.
- // Typically, you would only want to use MMX instructions when you have a reasonably
- // large number of pixels to work on. In this case your code can always be coded like
- // this:
- //
- // if (CountOfPixelsToDo >= g_MMXInfo.MinMMXOverCount())
- // {
- // Do MMX Stuff
- // } else {
- // Do integer / float based stuff
- // }
- //
- // If you code your MMX sequences like this, you will not have to use a special test
- // for the presence of MMX since the MinMMXOverCount will be set to 0xFFFFFFFF if there
- // is no MMX present on the processor.
- //
- // You do not need to use this unless your module needs to conditionally execute MMX vs
- // non-MMX code. If you only call the helper functions provided by DXTrans.Dll, such as
- // DXOverArrayMMX, you do NOT need this test. You can always call these functions and they
- // will use the MMX code path only when MMX instructions are present.
- //
- class CDXMMXInfo
- {
- ULONG m_MinMMXOver;
- public:
- CDXMMXInfo()
- {
- #ifndef _X86_
- m_MinMMXOver = 0xFFFFFFFF;
- #else
- m_MinMMXOver = DX_MMX_COUNT_CUTOFF;
- __try
- {
- __asm
- {
- //--- Try the MMX exit multi-media state instruction
- EMMS;
- }
- }
- __except( GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION )
- {
- //--- MMX instructions not available
- m_MinMMXOver = 0xFFFFFFFF;
- }
- #endif
- }
- inline ULONG MinMMXOverCount() { return m_MinMMXOver; }
- };
-
-
-
- //=== Function Prototypes ==========================================
- _DXTRANS_IMPL_EXT void WINAPI
- DXLinearInterpolateArray( const DXBASESAMPLE* pSamps, DXLIMAPINFO* pMapInfo,
- DXBASESAMPLE* pResults, DWORD dwResultCount );
- _DXTRANS_IMPL_EXT void WINAPI
- DXLinearInterpolateArray( const DXBASESAMPLE* pSamps, PUSHORT pIndexes,
- PBYTE pWeights, DXBASESAMPLE* pResults,
- DWORD dwResultCount );
-
- //
- // DXOverArray
- //
- // Composits an array of source samples over the samples in the pDest buffer.
- //
- // pDest - Pointer to the samples that will be modified by compositing the pSrc
- // samples over the pDest samples.
- // pSrc - The samples to composit over the pDest samples
- // nCount - The number of samples to process
- //
- _DXTRANS_IMPL_EXT void WINAPI
- DXOverArray(DXPMSAMPLE* pDest, const DXPMSAMPLE* pSrc, ULONG nCount);
-
- //
- // DXOverArrayMMX
- //
- // Identical to DXOverArray except that the MMX instruction set will be used for
- // large arrays of samples. If the CPU does not support MMX, you may still call
- // this function, which will perform the same operation without the use of the MMX
- // unit.
- //
- // Note that it is LESS EFFICIENT to use this function if the majority of the pixels
- // in the pSrc buffer are either clear (alpha 0) or opaque (alpha 0xFF). This is
- // because the MMX code must process every pixel and can not special case clear or
- // opaque pixels. If there are a large number of translucent pixels then this function
- // is much more efficent than DXOverArray.
- //
- // pDest - Pointer to the samples that will be modified by compositing the pSrc
- // samples over the pDest samples.
- // pSrc - The samples to composit over the pDest samples
- // nCount - The number of samples to process
- //
- _DXTRANS_IMPL_EXT void WINAPI
- DXOverArrayMMX(DXPMSAMPLE* pDest, const DXPMSAMPLE* pSrc, ULONG nCount);
-
- //
- // DXConstOverArray
- //
- // Composits a single color over an array of samples.
- //
- // pDest - Pointer to the samples that will be modified by compositing the color (val)
- // over the pDest samples.
- // val - The premultiplied color value to composit over the pDest array.
- // nCount - The number of samples to process
- //
- _DXTRANS_IMPL_EXT void WINAPI
- DXConstOverArray(DXPMSAMPLE* pDest, const DXPMSAMPLE & val, ULONG nCount);
-
- //
- // DXConstOverArray
- //
- // Composits a single color over an array of samples.
- //
- // pDest - Pointer to the samples that will be modified by compositing the samples
- // in the buffer over the color (val).
- // val - The premultiplied color value to composit under the pDest array.
- // nCount - The number of samples to process
- //
- _DXTRANS_IMPL_EXT void WINAPI
- DXConstUnderArray(DXPMSAMPLE* pDest, const DXPMSAMPLE & val, ULONG nCount);
-
- //===================================================================================
- //
- // Dithering Helpers
- //
- // Image transforms are sometimes asked to dither their output. This helper function
- // should be used by all image transforms to enusure a consistant dither pattern.
- //
- // DXDitherArray is used to dither pixels prior to writing them to a DXSurface.
- // The caller must fill in the DXDITHERDESC structure, setting X and Y to the
- // output surface X,Y coordinates that the pixels will be placed in. The samples
- // will be modified in place.
- //
- // Once the samples have been dithered, they should be written to or composited with
- // the destination surface.
- //
- #define DX_DITHER_HEIGHT 4 // The dither pattern is 4x4 pixels
- #define DX_DITHER_WIDTH 4
-
- typedef struct DXDITHERDESC
- {
- DXBASESAMPLE * pSamples; // Pointer to the 32-bit samples to dither
- ULONG cSamples; // Count of number of samples in pSamples buffer
- ULONG x; // X coordinate of the output surface
- ULONG y; // Y coordinate of the output surface
- DXSAMPLEFORMATENUM DestSurfaceFmt; // Pixel format of the output surface
- } DXDITHERDESC;
-
- _DXTRANS_IMPL_EXT void WINAPI
- DXDitherArray(const DXDITHERDESC *pDitherDesc);
-
- //=== Enumerated Set Definitions =============================================
-
-
- //=== Function Type Definitions ==============================================
-
-
- //=== Class, Struct and Union Definitions ====================================
-
-
- //=== Inline Functions =======================================================
-
- //===================================================================================
- //
- // Memory allocation helpers.
- //
- // These macros are used to allocate arrays of samples from the stack (using _alloca)
- // and cast them to the appropriate type. The ulNumSamples parameter is the count
- // of samples required.
- //
- #define DXBASESAMPLE_Alloca( ulNumSamples ) \
- (DXBASESAMPLE *)_alloca( (ulNumSamples) * sizeof( DXBASESAMPLE ) )
-
- #define DXSAMPLE_Alloca( ulNumSamples ) \
- (DXSAMPLE *)_alloca( (ulNumSamples) * sizeof( DXSAMPLE ) )
-
- #define DXPMSAMPLE_Alloca( ulNumSamples ) \
- (DXPMSAMPLE *)_alloca( (ulNumSamples) * sizeof( DXPMSAMPLE ) )
-
- //===================================================================================
- //
- // Critical section helpers.
- //
- // These C++ classes, CDXAutoObjectLock and CDXAutoCritSecLock are used within functions
- // to automatically claim critical sections upon constuction, and the critical section
- // will be released when the object is destroyed (goes out of scope).
- //
- // The macros DXAUTO_OBJ_LOCK and DX_AUTO_SEC_LOCK(s) are normally used at the beginning
- // of a function that requires a critical section. Any exit from the scope in which the
- // auto-lock was taken will automatically release the lock.
- //
-
- #ifdef __ATLCOM_H__ //--- Only enable these if ATL is being used
- class CDXAutoObjectLock
- {
- protected:
- CComObjectRootEx<CComMultiThreadModel>* m_pObject;
-
- public:
- CDXAutoObjectLock(CComObjectRootEx<CComMultiThreadModel> * const pobject)
- {
- m_pObject = pobject;
- m_pObject->Lock();
- };
-
- ~CDXAutoObjectLock() {
- m_pObject->Unlock();
- };
- };
-
- #define DXAUTO_OBJ_LOCK CDXAutoObjectLock lck(this);
- #define DXAUTO_OBJ_LOCK_( t ) CDXAutoObjectLock lck(t);
-
- class CDXAutoCritSecLock
- {
- protected:
- CComAutoCriticalSection* m_pSec;
-
- public:
- CDXAutoCritSecLock(CComAutoCriticalSection* pSec)
- {
- m_pSec = pSec;
- m_pSec->Lock();
- };
-
- ~CDXAutoCritSecLock()
- {
- m_pSec->Unlock();
- };
- };
-
- #define DXAUTO_SEC_LOCK( s ) CDXAutoCritSecLock lck(s);
- #endif // __ATLCOM_H__
-
- //--- This function is used to compute the coefficient for a gaussian filter coordinate
- inline float DXGaussCoeff( double x, double y, double Sigma )
- {
- double TwoSigmaSq = 2 * ( Sigma * Sigma );
- return (float)(exp( ( -(x*x + y*y) / TwoSigmaSq ) ) /
- ( 3.1415927 * TwoSigmaSq ));
- }
-
- //--- This function is used to initialize a gaussian convolution filter
- inline void DXInitGaussianFilter( float* pFilter, ULONG Width, ULONG Height, double Sigma )
- {
- int i, NumCoeff = Width * Height;
- float val, CoeffAdjust, FilterSum = 0.;
- double x, y;
- double LeftX = -(double)(Width / 2);
- double RightX = Width - LeftX;
- double TopY = -(double)(Height / 2);
- double BottomY = Height - TopY;
-
- for( y = -TopY; y <= BottomY; y += 1. )
- {
- for( x = -LeftX; x <= RightX; x += 1. )
- {
- val = DXGaussCoeff( x, y, Sigma );
- pFilter[i++] = val;
- }
- }
-
- //--- Normalize filter (make it sum to 1.0)
- for( i = 0; i < NumCoeff; ++i ) FilterSum += pFilter[i];
-
- if( FilterSum < 1. )
- {
- CoeffAdjust = 1.f / FilterSum;
- for( i = 0; i < NumCoeff; ++i )
- {
- pFilter[i] *= CoeffAdjust;
- }
- }
-
- } /* DXInitGaussianFilter*/
-
- //
- // DXConvertToGray
- //
- // Translates a color sample to a gray scale sample
- //
- // Sample - The sample to convert to gray scale.
- // Return value is the gray scale sample.
- //
- inline DXBASESAMPLE DXConvertToGray( DXBASESAMPLE Sample )
- {
- DWORD v = Sample;
- DWORD r = (BYTE)(v >> 16);
- DWORD g = (BYTE)(v >> 8);
- DWORD b = (BYTE)(v);
- DWORD sat = (r*306 + g*601 + b*117) / 1024;
- v &= 0xFF000000;
- v |= (sat << 16) | (sat << 8) | sat;
- return v;
- } /* DXConvertToGray */
-
- //--- This returns into the destination the value of the source
- // sample scaled by its own alpha (producing a premultiplied alpha sample)
- //
- inline DXPMSAMPLE DXPreMultSample(const DXSAMPLE & Src)
- {
- if(Src.Alpha == 255 )
- {
- return (DWORD)Src;
- }
- else if(Src.Alpha == 0 )
- {
- return 0;
- }
- else
- {
- unsigned t1, t2;
- t1 = (Src & 0x00ff00ff) * Src.Alpha + 0x00800080;
- t1 = ((t1 + ((t1 >> 8) & 0x00ff00ff)) >> 8) & 0x00ff00ff;
-
- t2 = (((Src >> 8) & 0x000000ff) | 0x01000000) * Src.Alpha + 0x00800080;
- t2 = (t2 + ((t2 >> 8) & 0x00ff00ff)) & 0xff00ff00;
- return (t1 | t2);
- }
- } /* DXPreMultSample */
-
- inline DXPMSAMPLE * DXPreMultArray(DXSAMPLE *pBuffer, ULONG cSamples)
- {
- for (ULONG i = 0; i < cSamples; i++)
- {
- BYTE SrcAlpha = pBuffer[i].Alpha;
- if (SrcAlpha != 0xFF)
- {
- if (SrcAlpha == 0)
- {
- pBuffer[i] = 0;
- }
- else
- {
- DWORD S = pBuffer[i];
- DWORD t1 = (S & 0x00ff00ff) * SrcAlpha + 0x00800080;
- t1 = ((t1 + ((t1 >> 8) & 0x00ff00ff)) >> 8) & 0x00ff00ff;
-
- DWORD t2 = (((S >> 8) & 0x000000ff) | 0x01000000) * SrcAlpha + 0x00800080;
- t2 = (t2 + ((t2 >> 8) & 0x00ff00ff)) & 0xff00ff00;
-
- pBuffer[i] = (t1 | t2);
- }
- }
- }
- return (DXPMSAMPLE *)pBuffer;
- }
-
-
- inline DXSAMPLE DXUnPreMultSample(const DXPMSAMPLE & Src)
- {
- if(Src.Alpha == 255 || Src.Alpha == 0)
- {
- return (DWORD)Src;
- }
- else
- {
- DXSAMPLE Dst;
- Dst.Blue = (BYTE)((Src.Blue * 255) / Src.Alpha);
- Dst.Green = (BYTE)((Src.Green * 255) / Src.Alpha);
- Dst.Red = (BYTE)((Src.Red * 255) / Src.Alpha);
- Dst.Alpha = Src.Alpha;
- return Dst;
- }
- } /* DXUnPreMultSample */
-
- inline DXSAMPLE * DXUnPreMultArray(DXPMSAMPLE *pBuffer, ULONG cSamples)
- {
- for (ULONG i = 0; i < cSamples; i++)
- {
- BYTE SrcAlpha = pBuffer[i].Alpha;
- if (SrcAlpha != 0xFF && SrcAlpha != 0)
- {
- pBuffer[i].Blue = (BYTE)((pBuffer[i].Blue * 255) / SrcAlpha);
- pBuffer[i].Green = (BYTE)((pBuffer[i].Green * 255) / SrcAlpha);
- pBuffer[i].Red = (BYTE)((pBuffer[i].Red * 255) / SrcAlpha);
- }
- }
- return (DXSAMPLE *)pBuffer;
- }
-
-
- //
- // This returns the result of 255-Alpha which is computed by doing a NOT
- //
- inline BYTE DXInvertAlpha( BYTE Alpha ) { return (BYTE)~Alpha; }
-
- inline DWORD DXScaleSample( DWORD Src, ULONG beta )
- {
- ULONG t1, t2;
-
- t1 = (Src & 0x00ff00ff) * beta + 0x00800080;
- t1 = ((t1 + ((t1 >> 8) & 0x00ff00ff)) >> 8) & 0x00ff00ff;
-
- t2 = ((Src >> 8) & 0x00ff00ff) * beta + 0x00800080;
- t2 = (t2 + ((t2 >> 8) & 0x00ff00ff)) & 0xff00ff00;
-
- return (DWORD)(t1 | t2);
- }
-
-
- inline DWORD DXScaleSamplePercent( DWORD Src, float Percent )
- {
- if (Percent > (254.0f / 255.0f)) {
- return Src;
- }
- else
- {
- return DXScaleSample(Src, (BYTE)(Percent * 255));
- }
- }
-
- inline void DXCompositeOver(DXPMSAMPLE & Dst, const DXPMSAMPLE & Src)
- {
- if (Src.Alpha)
- {
- ULONG Beta = DXInvertAlpha(Src.Alpha);
- if (Beta)
- {
- Dst = Src + DXScaleSample(Dst, Beta);
- }
- else
- {
- Dst = Src;
- }
- }
- }
-
-
- inline DXPMSAMPLE DXCompositeUnder(DXPMSAMPLE Dst, DXPMSAMPLE Src )
- {
- return Dst + DXScaleSample(Src, DXInvertAlpha(Dst.Alpha));
- }
-
-
- inline DXBASESAMPLE DXApplyLookupTable(const DXBASESAMPLE Src, const BYTE * pTable)
- {
- DXBASESAMPLE Dest;
- Dest.Blue = pTable[Src.Blue];
- Dest.Green = pTable[Src.Green];
- Dest.Red = pTable[Src.Red];
- Dest.Alpha = pTable[Src.Alpha];
- return Dest;
- }
-
- inline DXBASESAMPLE * DXApplyLookupTableArray(DXBASESAMPLE *pBuffer, ULONG cSamples, const BYTE * pTable)
- {
- for (ULONG i = 0; i < cSamples; i++)
- {
- DWORD v = pBuffer[i];
- DWORD a = pTable[v >> 24];
- DWORD r = pTable[(BYTE)(v >> 16)];
- DWORD g = pTable[(BYTE)(v >> 8)];
- DWORD b = pTable[(BYTE)v];
- pBuffer[i] = (a << 24) | (r << 16) | (g << 8) | b;
- }
- return pBuffer;
- }
-
- inline DXBASESAMPLE * DXApplyColorChannelLookupArray(DXBASESAMPLE *pBuffer,
- ULONG cSamples,
- const BYTE * pAlphaTable,
- const BYTE * pRedTable,
- const BYTE * pGreenTable,
- const BYTE * pBlueTable)
- {
- for (ULONG i = 0; i < cSamples; i++)
- {
- pBuffer[i].Blue = pBlueTable[pBuffer[i].Blue];
- pBuffer[i].Green = pGreenTable[pBuffer[i].Green];
- pBuffer[i].Red = pRedTable[pBuffer[i].Red];
- pBuffer[i].Alpha = pAlphaTable[pBuffer[i].Alpha];
- }
- return pBuffer;
- }
-
-
- //
- // CDXScale helper class
- //
- // This class uses a pre-computed lookup table to scale samples. For scaling large
- // arrays of samples to a constant scale, this is much faster than using even MMX
- // instructions. This class is usually declared as a member of another class and
- // is most often used to apply a global opacity to a set of samples.
- //
- // When using this class, you must always check for the two special cases of clear
- // and opaque before calling any of the scaling member functions. Do this by using
- // the ScaleType() inline function. Your code should look somthing like this:
- //
- // if (ScaleType() == DXRUNTYPE_CLEAR)
- // Do whatever you do for a 0 alpha set of samples -- usually just ignore them
- // else if (ScaleType() == DXRUNTYPE_OPAQUE)
- // Do whatever you would do for a non-scaled set of samples
- // else
- // Scale the samples by using ScaleSample or one of the ScaleArray members
- //
- // If you call any of the scaling members when the ScaleType() is either clear or
- // opaque, you will GP fault becuase the lookup table will not be allocated.
- //
- // The scale can be set using either a floating point number between 0 and 1 using:
- // CDXScale::SetScale / CDXScale::GetScale
- // or you can use a byte integer value by using:
- // CDXScale::SetScaleAlphaValue / CDXScale::GetScaleAlphaValue
- //
- class CDXScale
- {
- private:
- float m_Scale;
- BYTE m_AlphaScale;
- BYTE *m_pTable;
-
- HRESULT InternalSetScale(BYTE Scale)
- {
- if (m_AlphaScale == Scale) return S_OK;
- if (Scale == 0 || Scale == 255)
- {
- delete m_pTable;
- m_pTable = NULL;
- }
- else
- {
- if(!m_pTable)
- {
- m_pTable = new BYTE[256];
- if(!m_pTable )
- {
- return E_OUTOFMEMORY;
- }
- }
- for (int i = 0; i < 256; ++i )
- {
- m_pTable[i] = (BYTE)((i * Scale) / 255);
- }
- }
- m_AlphaScale = Scale;
- return S_OK;
- }
- public:
- CDXScale() :
- m_Scale(1.0f),
- m_AlphaScale(0xFF),
- m_pTable(NULL)
- {}
- ~CDXScale()
- {
- delete m_pTable;
- }
- DXRUNTYPE ScaleType()
- {
- if (m_AlphaScale == 0) return DXRUNTYPE_CLEAR;
- if (m_AlphaScale == 0xFF) return DXRUNTYPE_OPAQUE;
- return DXRUNTYPE_TRANS;
- }
- HRESULT SetScaleAlphaValue(BYTE Alpha)
- {
- HRESULT hr = InternalSetScale(Alpha);
- if (SUCCEEDED(hr))
- {
- m_Scale = ((float)Alpha) / 255.0f;
- }
- return hr;
- }
- BYTE GetScaleAlphaValue(void)
- {
- return m_AlphaScale;
- }
- HRESULT SetScale(float Scale)
- {
- HRESULT hr = S_OK;
- if(( Scale < 0.0f ) || ( Scale > 1.0f ) )
- {
- hr = E_INVALIDARG;
- }
- else
- {
- ULONG IntScale = (ULONG)(Scale * 256.0f); // Round up alpha (.9999 = 255 = Solid)
- if (IntScale > 255)
- {
- IntScale = 255;
- }
- hr = SetScaleAlphaValue((BYTE)IntScale);
- if (SUCCEEDED(hr))
- {
- m_Scale = Scale;
- }
- }
- return hr;
- }
- float GetScale() const
- {
- return m_Scale;
- }
- DXRUNTYPE ScaleType() const
- {
- return (m_pTable ? DXRUNTYPE_TRANS : (m_AlphaScale ? DXRUNTYPE_OPAQUE : DXRUNTYPE_CLEAR));
- }
- DWORD ScaleSample(const DWORD s) const
- {
- return DXApplyLookupTable((DXBASESAMPLE)s, m_pTable);
- }
- DXBASESAMPLE * ScaleBaseArray(DXBASESAMPLE * pBuffer, ULONG cSamples) const
- {
- return DXApplyLookupTableArray(pBuffer, cSamples, m_pTable);
- }
- DXPMSAMPLE * ScalePremultArray(DXPMSAMPLE * pBuffer, ULONG cSamples) const
- {
- return (DXPMSAMPLE *)DXApplyLookupTableArray(pBuffer, cSamples, m_pTable);
- }
- DXSAMPLE * ScaleArray(DXSAMPLE * pBuffer, ULONG cSamples) const
- {
- return (DXSAMPLE *)DXApplyLookupTableArray(pBuffer, cSamples, m_pTable);
- }
- DXSAMPLE * ScaleArrayAlphaOnly(DXSAMPLE *pBuffer, ULONG cSamples) const
- {
- const BYTE *pTable = m_pTable;
- for (ULONG i = 0; i < cSamples; i++)
- {
- pBuffer[i].Alpha = pTable[pBuffer[i].Alpha];
- }
- return pBuffer;
- }
- };
-
- inline DWORD DXWeightedAverage( DXBASESAMPLE S1, DXBASESAMPLE S2, ULONG Wgt )
- {
- _ASSERT( Wgt < 256 );
- ULONG t1, t2;
- ULONG InvWgt = Wgt ^ 0xFF;
-
- t1 = (((S1 & 0x00ff00ff) * Wgt) + ((S2 & 0x00ff00ff) * InvWgt )) + 0x00800080;
- t1 = ((t1 + ((t1 >> 8) & 0x00ff00ff)) >> 8) & 0x00ff00ff;
-
- t2 = ((((S1 >> 8) & 0x00ff00ff) * Wgt) + (((S2 >> 8) & 0x00ff00ff) * InvWgt )) + 0x00800080;
- t2 = (t2 + ((t2 >> 8) & 0x00ff00ff)) & 0xff00ff00;
-
- return (t1 | t2);
- } /* DXWeightedAverage */
-
- inline void DXWeightedAverageArray( DXBASESAMPLE* pS1, DXBASESAMPLE* pS2, ULONG Wgt,
- DXBASESAMPLE* pResults, DWORD dwCount )
- {
- _ASSERT( pS1 && pS2 && pResults && dwCount );
- for( DWORD i = 0; i < dwCount; ++i )
- {
- pResults[i] = DXWeightedAverage( pS1[i], pS2[i], Wgt );
- }
- } /* DXWeightedAverageArray */
-
- inline void DXWeightedAverageArrayOver( DXPMSAMPLE* pS1, DXPMSAMPLE* pS2, ULONG Wgt,
- DXPMSAMPLE* pResults, DWORD dwCount )
- {
- _ASSERT( pS1 && pS2 && pResults && dwCount );
- DWORD i;
-
- if( Wgt == 255 )
- {
- for( i = 0; i < dwCount; ++i )
- {
- DXCompositeOver( pResults[i], pS1[i] );
- }
- }
- else
- {
- for( i = 0; i < dwCount; ++i )
- {
- DXPMSAMPLE Avg = DXWeightedAverage( (DXBASESAMPLE)pS1[i],
- (DXBASESAMPLE)pS2[i], Wgt );
- DXCompositeOver( pResults[i], Avg );
- }
- }
-
- } /* DXWeightedAverageArrayOver */
-
- inline void DXScalePremultArray(DXPMSAMPLE *pBuffer, ULONG cSamples, BYTE Weight)
- {
- for (DXPMSAMPLE *pBuffLimit = pBuffer + cSamples; pBuffer < pBuffLimit; pBuffer++)
- {
- *pBuffer = DXScaleSample(*pBuffer, Weight);
- }
- }
-
-
-
- //
- //
- inline HRESULT DXClipToOutputWithPlacement(CDXDBnds & LogicalOutBnds, const CDXDBnds * pClipBnds, CDXDBnds & PhysicalOutBnds, const CDXDVec *pPlacement)
- {
- if(pClipBnds && (!LogicalOutBnds.IntersectBounds(*pClipBnds)))
- {
- return S_FALSE; // no intersect, we're done
- }
- else
- {
- CDXDVec vClipPos(false);
- LogicalOutBnds.GetMinVector( vClipPos );
- if (pPlacement)
- {
- vClipPos -= *pPlacement;
- }
- PhysicalOutBnds += vClipPos;
- if (!LogicalOutBnds.IntersectBounds(PhysicalOutBnds))
- {
- return S_FALSE;
- }
- PhysicalOutBnds = LogicalOutBnds;
- PhysicalOutBnds -= vClipPos;
- }
- return S_OK;
- }
-
-
-
- //
- // Helper for converting a color ref to a DXSAMPLE
- //
- inline DWORD DXSampleFromColorRef(COLORREF cr)
- {
- DXSAMPLE Samp(0xFF, GetRValue(cr), GetGValue(cr), GetBValue(cr));
- return Samp;
- }
-
- //
- // Fill an entire surface with a color
- //
- inline HRESULT DXFillSurface( IDXSurface *pSurface, DXPMSAMPLE Color,
- BOOL bDoOver = FALSE, ULONG ulTimeOut = 10000 )
- {
- IDXARGBReadWritePtr * pPtr;
- HRESULT hr = pSurface->LockSurface( NULL, ulTimeOut, DXLOCKF_READWRITE,
- IID_IDXARGBReadWritePtr, (void **)&pPtr, NULL);
- if( SUCCEEDED(hr) )
- {
- pPtr->FillRect(NULL, Color, bDoOver);
- pPtr->Release();
- }
- return hr;
- } /* DXFillSurface */
-
- //
- // Fill a specified sub-rectangle of a surface with a color.
- //
- inline HRESULT DXFillSurfaceRect( IDXSurface *pSurface, RECT & rect, DXPMSAMPLE Color,
- BOOL bDoOver = FALSE, ULONG ulTimeOut = 10000 )
- {
- CDXDBnds bnds(rect);
- IDXARGBReadWritePtr * pPtr;
- HRESULT hr = pSurface->LockSurface( &bnds, ulTimeOut, DXLOCKF_READWRITE,
- IID_IDXARGBReadWritePtr, (void **)&pPtr, NULL);
- if( SUCCEEDED(hr) )
- {
- pPtr->FillRect(NULL, Color, bDoOver);
- pPtr->Release();
- }
- return hr;
- } /* DXFillSurfaceRect */
-
-
-
- //
- // The DestBnds height and width must be greater than or equal to the source bounds.
- //
- // The dwFlags parameter uses the flags defined by IDXSurfaceFactory::BitBlt:
- //
- // DXBOF_DO_OVER
- // DXBOF_DITHER
- //
- inline HRESULT DXBitBlt(IDXSurface * pDest, const CDXDBnds & DestBnds, IDXSurface * pSrc, const CDXDBnds & SrcBnds, DWORD dwFlags, ULONG ulTimeout)
- {
- IDXARGBReadPtr * pIn;
- HRESULT hr;
- hr = pSrc->LockSurface( &SrcBnds, INFINITE,
- (dwFlags & DXBOF_DO_OVER) ? (DXLOCKF_READ | DXLOCKF_WANTRUNINFO) : DXLOCKF_READ,
- IID_IDXARGBReadPtr, (void**)&pIn, NULL);
- if(SUCCEEDED(hr))
- {
- IDXARGBReadWritePtr * pOut;
- hr = pDest->LockSurface( &DestBnds, INFINITE, DXLOCKF_READWRITE,
- IID_IDXARGBReadWritePtr, (void**)&pOut, NULL );
- if (SUCCEEDED(hr))
- {
- DXSAMPLEFORMATENUM InNativeType = pIn->GetNativeType(NULL);
- DXSAMPLEFORMATENUM OutNativeType = pOut->GetNativeType(NULL);
- BOOL bSrcIsOpaque = !(InNativeType & (DXPF_TRANSLUCENCY | DXPF_TRANSPARENCY));
- const ULONG Width = SrcBnds.Width();
- DXPMSAMPLE *pSrcBuff = NULL;
- if( InNativeType != DXPF_PMARGB32 )
- {
- pSrcBuff = DXPMSAMPLE_Alloca(Width);
- }
- //
- // Don't dither unless the dest has a greater error term than the source.
- //
- if ((dwFlags & DXBOF_DITHER) &&
- ((OutNativeType & DXPF_ERRORMASK) <= (InNativeType & DXPF_ERRORMASK)))
- {
- dwFlags &= (~DXBOF_DITHER);
- }
- if ((dwFlags & DXBOF_DITHER) || ((dwFlags & DXBOF_DO_OVER) && bSrcIsOpaque== 0))
- {
- //--- Allocate a working output buffer if necessary
- DXPMSAMPLE *pDestBuff = NULL;
- if( OutNativeType != DXPF_PMARGB32 )
- {
- pDestBuff = DXPMSAMPLE_Alloca(Width);
- }
- //--- Process each output row
- // Note: Output coordinates are relative to the lock region
- const ULONG Height = SrcBnds.Height();
- if (dwFlags & DXBOF_DITHER)
- {
- DXPMSAMPLE * pSrcDitherBuff = pSrcBuff;
- if (pSrcDitherBuff == NULL)
- {
- pSrcDitherBuff = DXPMSAMPLE_Alloca(Width);
- }
- const BOOL bCopy = ((dwFlags & DXBOF_DO_OVER) == 0);
- //
- // Set up the dither descriptor (some things are constant)
- //
- DXDITHERDESC dd;
- dd.pSamples = pSrcDitherBuff;
- dd.DestSurfaceFmt = OutNativeType;
- for(ULONG Y = 0; Y < Height; ++Y )
- {
- dd.x = DestBnds.Left();
- dd.y = DestBnds.Top() + Y;
- const DXRUNINFO *pRunInfo;
- ULONG cRuns = pIn->MoveAndGetRunInfo(Y, &pRunInfo);
- pOut->MoveToRow( Y );
- do
- {
- ULONG ulRunLen = pRunInfo->Count;
- if (pRunInfo->Type == DXRUNTYPE_CLEAR)
- {
- pIn->Move(ulRunLen);
- if (bCopy)
- {
- //
- // The only way to avoid calling a constructor function to create
- // a pmsample from 0 is to declare a variable and then assign it!
- //
- DXPMSAMPLE NullColor;
- NullColor = 0;
- pOut->FillAndMove(pSrcDitherBuff, NullColor, ulRunLen, FALSE);
- }
- else
- {
- pOut->Move(ulRunLen);
- }
- dd.x += ulRunLen;
- }
- else
- {
- pIn->UnpackPremult(pSrcDitherBuff, ulRunLen, TRUE);
- dd.cSamples = ulRunLen;
- DXDitherArray(&dd);
- dd.x += ulRunLen;
- if (bCopy || pRunInfo->Type == DXRUNTYPE_OPAQUE)
- {
- pOut->PackPremultAndMove(pSrcDitherBuff, ulRunLen);
- }
- else
- {
- pOut->OverArrayAndMove(pDestBuff, pSrcDitherBuff, ulRunLen);
- }
- }
- pRunInfo++;
- cRuns--;
- } while (cRuns);
- }
- }
- else
- {
- for(ULONG Y = 0; Y < Height; ++Y )
- {
- const DXRUNINFO *pRunInfo;
- ULONG cRuns = pIn->MoveAndGetRunInfo(Y, &pRunInfo);
- pOut->MoveToRow( Y );
- do
- {
- ULONG ulRunLen = pRunInfo->Count;
- switch (pRunInfo->Type)
- {
- case DXRUNTYPE_CLEAR:
- pIn->Move(ulRunLen);
- pOut->Move(ulRunLen);
- break;
- case DXRUNTYPE_OPAQUE:
- pOut->CopyAndMoveBoth(pDestBuff, pIn, ulRunLen, TRUE);
- break;
- case DXRUNTYPE_TRANS:
- {
- DXPMSAMPLE *pSrc = pIn->UnpackPremult(pSrcBuff, ulRunLen, TRUE);
- DXPMSAMPLE *pDest = pOut->UnpackPremult(pDestBuff, ulRunLen, FALSE);
- DXOverArrayMMX(pDest, pSrc, ulRunLen);
- pOut->PackPremultAndMove(pDestBuff, ulRunLen);
- break;
- }
-
- case DXRUNTYPE_UNKNOWN:
- {
- pOut->OverArrayAndMove(pDestBuff,
- pIn->UnpackPremult(pSrcBuff, ulRunLen, TRUE),
- ulRunLen);
- break;
- }
- }
- pRunInfo++;
- cRuns--;
- } while (cRuns);
- }
- }
- }
- else
- {
- pOut->CopyRect( pSrcBuff, NULL, pIn, NULL, bSrcIsOpaque );
- }
- pOut->Release();
- }
- pIn->Release();
- }
- return hr;
- }
-
- inline HRESULT DXSrcCopy(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight,
- IDXSurface *pSrcSurface, int nXSrc, int nYSrc)
- {
- IDXDCLock *pDCLock;
- HRESULT hr = pSrcSurface->LockSurfaceDC(NULL, INFINITE, DXLOCKF_READ, &pDCLock);
- if (SUCCEEDED(hr))
- {
- ::BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, pDCLock->GetDC(), nXSrc, nYSrc, SRCCOPY);
- pDCLock->Release();
- }
- return hr;
- }
- //
- //=== Pointer validation functions
- //
- inline BOOL DXIsBadReadPtr( const void* pMem, UINT Size )
- {
- #if !defined( _DEBUG ) && defined( DXTRANS_NOROBUST )
- return false;
- #else
- return ::IsBadReadPtr( pMem, Size );
- #endif
- }
-
- inline BOOL DXIsBadWritePtr( void* pMem, UINT Size )
- {
- #if !defined( _DEBUG ) && defined( DXTRANS_NOROBUST )
- return false;
- #else
- return ::IsBadWritePtr( pMem, Size );
- #endif
- }
-
-
- inline BOOL DXIsBadInterfacePtr( const IUnknown* pUnknown )
- {
- #if !defined( _DEBUG ) && defined( DXTRANS_NOROBUST )
- return false;
- #else
- return ( ::IsBadReadPtr( pUnknown, sizeof( *pUnknown ) ) ||
- ::IsBadCodePtr( (FARPROC)((PDWORD)pUnknown)[0] ))?
- (true):(false);
- #endif
- }
-
- #define DX_IS_BAD_OPTIONAL_WRITE_PTR(p) ((p) && DXIsBadWritePtr(p, sizeof(p)))
- #define DX_IS_BAD_OPTIONAL_READ_PTR(p) ((p) && DXIsBadReadPtr(p, sizeof(p)))
- #define DX_IS_BAD_OPTIONAL_INTERFACE_PTR(p) ((p) && DXIsBadInterfacePtr(p))
-
-
- #pragma option pop /*P_O_Pop*/
- #endif /* This must be the last line in the file */
-