Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

239 lines
6.6 KiB

/******************************Module*Header*******************************\
* Module Name: CVPMFilter.cpp
*
*
*
*
* Created: Tue 02/15/2000
* Author: Glenn Evans [GlennE]
*
* Copyright (c) 2000 Microsoft Corporation
\**************************************************************************/
#include <streams.h>
#include <DRect.h>
#if 1
#include <math.h>
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;
}
}
}