mirror of https://github.com/tongzx/nt5src
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
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;
|
|
}
|
|
}
|
|
}
|