/******************************Module*Header*******************************\ * Module Name: CVPMFilter.cpp * * * * * Created: Tue 02/15/2000 * Author: Glenn Evans [GlennE] * * Copyright (c) 2000 Microsoft Corporation \**************************************************************************/ #include #include #if 1 #include static double myfloor(double dNumber) { return floor( dNumber ); } static double myceil(double dNumber) { return ceil( dNumber ); } #else // have to define my own floor inorder to avoid pulling in the C runtime static double myfloor(double dNumber) { // cast it to LONGLONG to get rid of the fraction LONGLONG llNumber = (LONGLONG)dNumber; if ((dNumber > 0) && ((double)llNumber > dNumber)) { // need to push ccNumber towards zero (eg 5.7) return (double)(llNumber-1); } else if ((dNumber < 0) && ((double)llNumber < dNumber)) { // need to push ccNumber towards zero (eg -5.7) return (double)(llNumber+1); } else { // numbers like 5.3 or -5.3 return (double)(llNumber); } } // have to define my own ceil inorder to avoid pulling in the C runtime static double myceil(double dNumber) { // cast it to LONGLONG to get rid of the fraction LONGLONG llNumber = (LONGLONG)dNumber; if ((dNumber > 0) && ((double)llNumber < dNumber)) { // need to push ccNumber away from zero (eg 5.3) return (double)(llNumber+1); } else if ((dNumber < 0) && ((double)llNumber > dNumber)) { // need to push ccNumber away from zero (eg -5.3) return (double)(llNumber-1); } else { // numbers like 5.7 or -5.7 return (double)(llNumber); } } #endif // this in a way defines the error margin #define EPSILON 0.0001 // this is a function implemented solely to handle floating point rounding errors. // dEpsilon defines the error margin. So if a floating point number is within I-e, I+e (inclusive) // (I is an integer, e is dEpsilon), we return its floor as I itself, otherwise we go to the // base defintion of myfloor static double myfloor(double dNumber, double dEpsilon) { if (dNumber > dEpsilon) return myfloor(dNumber + dEpsilon); else if (dNumber < -dEpsilon) return myfloor(dNumber - dEpsilon); else return 0; } // this is a function implemented solely to handle floating point rounding errors. // dEpsilon defines the error margin. So if a floating point number is within I-e, I+e (inclusive) // (I is an integer, e is dEpsilon), we return its ceil as I itself, otherwise we go to the // base defintion of myceil static double myceil(double dNumber, double dEpsilon) { if (dNumber > dEpsilon) return myceil(dNumber - dEpsilon); else if (dNumber < -dEpsilon) return myceil(dNumber + dEpsilon); else return 0; } DRect::DRect( const RECT& rc ) : m_left( rc.left ) , m_right( rc.right ) , m_top( rc.top ) , m_bottom( rc.bottom ) { } RECT DRect::AsRECT() const { RECT rRect; rRect.left = (LONG)myfloor(m_left, EPSILON); rRect.top = (LONG)myfloor(m_top, EPSILON); rRect.right = (LONG)myceil(m_right, EPSILON); rRect.bottom = (LONG)myceil(m_bottom, EPSILON); return rRect; } DRect DRect::IntersectWith( const DRect& drect ) const { return DRect( max( drect.m_left, m_left), max( drect.m_top, m_top), min( drect.m_right, m_right), min( drect.m_bottom, m_bottom)); } // just a helper function to scale a DRECT void DRect::Scale( double dScaleX, double dScaleY ) { m_left *= dScaleX; m_right *= dScaleX; m_top *= dScaleY; m_bottom *= dScaleY; } // just a helper function, to get the letterboxed or cropped rect // Puts the transformed rectangle into pRect. double DRect::CorrectAspectRatio( double dPictAspectRatio, BOOL bShrink ) { double dWidth, dHeight, dNewWidth, dNewHeight; dNewWidth = dWidth = GetWidth(); dNewHeight = dHeight = GetHeight(); ASSERT( dWidth > 0 ); ASSERT( dHeight > 0 ); double dResolutionRatio = dWidth / dHeight; double dTransformRatio = dPictAspectRatio / dResolutionRatio; // shrinks one dimension to maintain the coorect aspect ratio if ( bShrink ) { if (dTransformRatio > 1.0) { dNewHeight = dNewHeight / dTransformRatio; } else if (dTransformRatio < 1.0) { dNewWidth = dNewWidth * dTransformRatio; } } // stretches one dimension to maintain the coorect aspect ratio else { if (dTransformRatio > 1.0) { dNewWidth = dNewWidth * dTransformRatio; } else if (dTransformRatio < 1.0) { dNewHeight = dNewHeight / dTransformRatio; } } // cut or add equal portions to the changed dimension m_left += (dWidth - dNewWidth)/2.0; m_right = m_left + dNewWidth; m_top += (dHeight - dNewHeight)/2.0; m_bottom = m_top + dNewHeight; return dTransformRatio; } /******************************Private*Routine******************************\ * ClipWith * * Clip a destination rectangle & update the scaled source accordingly * * * History: * Fri 04/07/2000 - GlennE - Created * \**************************************************************************/ void DRect::ClipWith(const DRect& rdWith, DRect *pUpdate ) { // figure out src/dest scale ratios double dUpdateWidth = pUpdate->GetWidth(); double dUpdateHeight = pUpdate->GetHeight(); double dDestWidth = GetWidth(); double dDestHeight = GetHeight(); // clip destination (and adjust the source when we change the destination) // see if we have to clip horizontally if( dDestWidth ) { if( rdWith.m_left > m_left ) { double dDelta = rdWith.m_left - m_left; m_left += dDelta; double dDeltaSrc = dDelta*dUpdateWidth/dDestWidth; pUpdate->m_left += dDeltaSrc; } if( rdWith.m_right < m_right ) { double dDelta = m_right-rdWith.m_right; m_right -= dDelta; double dDeltaSrc = dDelta*dUpdateWidth/dDestWidth; pUpdate->m_right -= dDeltaSrc; } } // see if we have to clip vertically if( dDestHeight ) { if( rdWith.m_top > m_top ) { double dDelta = rdWith.m_top - m_top; m_top += dDelta; double dDeltaSrc = dDelta*dUpdateHeight/dDestHeight; pUpdate->m_top += dDeltaSrc; } if( rdWith.m_bottom < m_bottom ) { double dDelta = m_bottom-rdWith.m_bottom; m_bottom -= dDelta; double dDeltaSrc = dDelta*dUpdateHeight/dDestHeight; pUpdate->m_bottom -= dDeltaSrc; } } }