Microsoft-3D-Movie-Maker/kauai/SRC/UTILINT.H

644 lines
17 KiB
C++

/* Copyright (c) Microsoft Corporation.
Licensed under the MIT License. */
/* Copyright (c) Microsoft Corporation.
Licensed under the MIT License. */
/***************************************************************************
Author: ShonK
Project: Kauai
Reviewed:
Copyright (c) Microsoft Corporation
Scalar, rectangle and point declarations
***************************************************************************/
#ifndef UTILINT_H
#define UTILINT_H
/****************************************
Scalar constants
****************************************/
const bool fTrue = 1;
const bool fFalse = 0;
enum
{
tNo,
tYes,
tMaybe,
tLim
};
#define AssertT(t) AssertIn(t, 0, tLim)
// standard comparison flags
enum
{
fcmpEq = 0x0001,
fcmpGt = 0x0002,
fcmpLt = 0x0004,
};
const ulong kgrfcmpGe = (fcmpEq | fcmpGt);
const ulong kgrfcmpLe = (fcmpEq | fcmpLt);
const ulong kgrfcmpNe = (fcmpGt | fcmpLt);
#define FPure(f) ((f) != fFalse)
#define ivNil (-1L)
#define bvNil (-1L)
#define cvNil (-1L)
#define pvNil 0
/****************************************
Memory access asserts
****************************************/
#ifdef DEBUG
void AssertPvCb(void *pv, long cb);
inline void AssertNilOrPvCb(void *pv, long cb)
{ if (pv != pvNil) AssertPvCb(pv, cb); }
#else //!DEBUG
#define AssertPvCb(pv, cb)
#define AssertNilOrPvCb(pv, cb)
#endif //!DEBUG
#define AssertThisMem() AssertPvCb(this, size(*this))
#define AssertVarMem(pvar) AssertPvCb(pvar, size(*(pvar)))
#define AssertNilOrVarMem(pvar) AssertNilOrPvCb(pvar, size(*(pvar)))
/****************************************
Scalar APIs
****************************************/
inline bool FIn(long lw, long lwMin, long lwLim)
{ return lw >= lwMin && lw < lwLim; }
inline long LwBound(long lw, long lwMin, long lwMax)
{ return lw < lwMin ? lwMin : lw >= lwMax ? lwMax - 1 : lw; }
void SortLw(long *plw1, long *plw2);
inline short SwHigh(long lw)
{ return (short)(lw >> 16); }
inline short SwLow(long lw)
{ return (short)lw; }
inline long LwHighLow(short swHigh, short swLow)
{ return ((long)swHigh << 16) | (long)(ushort)swLow; }
inline ulong LuHighLow(ushort suHigh, ushort suLow)
{ return ((ulong)suHigh << 16) | (ulong)suLow; }
inline byte B0Lw(long lw)
{ return (byte)lw; }
inline byte B1Lw(long lw)
{ return (byte)(lw >> 8); }
inline byte B2Lw(long lw)
{ return (byte)(lw >> 16); }
inline byte B3Lw(long lw)
{ return (byte)(lw >> 24); }
inline long LwFromBytes(byte b3, byte b2, byte b1, byte b0)
{ return ((long)b3 << 24) | ((long)b2 << 16) | ((long)b1 << 8) | (long)b0; }
inline ushort SuHigh(long lw)
{ return (ushort)((ulong)lw >> 16); }
inline ushort SuLow(long lw)
{ return (ushort)lw; }
inline byte BHigh(short sw)
{ return (byte)((ushort)sw >> 8); }
inline byte BLow(short sw)
{ return (byte)sw; }
inline short SwHighLow(byte bHigh, byte bLow)
{ return ((short)bHigh << 8) | (short)bLow; }
inline ushort SuHighLow(byte bHigh, byte bLow)
{ return ((ushort)bHigh << 8) | (ushort)bLow; }
inline short SwTruncLw(long lw)
{ return lw <= kswMax ? (lw >= kswMin ? (short)lw : kswMin) : kswMax; }
inline short SwMin(short sw1, short sw2)
{ return sw1 < sw2 ? sw1 : sw2; }
inline short SwMax(short sw1, short sw2)
{ return sw1 >= sw2 ? sw1 : sw2; }
inline ushort SuMin(ushort su1, ushort su2)
{ return su1 < su2 ? su1 : su2; }
inline ushort SuMax(ushort su1, ushort su2)
{ return su1 >= su2 ? su1 : su2; }
inline long LwMin(long lw1, long lw2)
{ return lw1 < lw2 ? lw1 : lw2; }
inline long LwMax(long lw1, long lw2)
{ return lw1 >= lw2 ? lw1 : lw2; }
inline ulong LuMin(ulong lu1, ulong lu2)
{ return lu1 < lu2 ? lu1 : lu2; }
inline ulong LuMax(ulong lu1, ulong lu2)
{ return lu1 >= lu2 ? lu1 : lu2; }
inline short SwAbs(short sw)
{ return sw < 0 ? -sw : sw; }
inline long LwAbs(long lw)
{ return lw < 0 ? -lw : lw; }
inline long LwMulSw(short sw1, short sw2)
{ return (long)sw1 * sw2; }
#ifdef MC_68020
/***************************************************************************
Motorola 68020 routines.
***************************************************************************/
extern "C"
{
long __cdecl LwMulDiv(long lw, long lwMul, long lwDiv);
void __cdecl MulLw(long lw1, long lw2, long *plwHigh, ulong *pluLow);
ulong __cdecl LuMulDiv(ulong lu, ulong luMul, ulong luDiv);
void __cdecl MulLu(ulong lu1, ulong lu2, ulong *pluHigh, ulong *pluLow);
}
long LwMulDivMod(long lw, long lwMul, long lwDiv, long *plwRem);
#elif defined(IN_80386)
/***************************************************************************
Intel 80386 routines.
***************************************************************************/
inline long LwMulDiv(long lw, long lwMul, long lwDiv)
{
AssertH(lwDiv != 0);
__asm
{
mov eax,lw
imul lwMul
idiv lwDiv
mov lw,eax
}
return lw;
}
inline long LwMulDivMod(long lw, long lwMul, long lwDiv, long *plwRem)
{
AssertH(lwDiv != 0);
AssertVarMem(plwRem);
__asm
{
mov eax,lw
imul lwMul
idiv lwDiv
mov ecx,plwRem
mov DWORD PTR[ecx],edx
mov lw,eax
}
return lw;
}
void MulLw(long lw1, long lw2, long *plwHigh, ulong *pluLow);
ulong LuMulDiv(ulong lu, ulong luMul, ulong luDiv);
void MulLu(ulong lu1, ulong lu2, ulong *pluHigh, ulong *pluLow);
#else //!MC_68020 && !IN_80386
/***************************************************************************
Other processors. These generally use floating point.
***************************************************************************/
long LwMulDiv(long lw, long lwMul, long lwDiv);
long LwMulDivMod(long lw, long lwMul, long lwDiv, long *plwRem);
void MulLw(long lw1, long lw2, long *plwHigh, ulong *pluLow);
ulong LuMulDiv(ulong lu, ulong luMul, ulong luDiv);
void MulLu(ulong lu1, ulong lu2, ulong *pluHigh, ulong *pluLow);
#endif //!MC_68020 && !IN_80386
long LwMulDivAway(long lw, long lwMul, long lwDiv);
ulong LuMulDivAway(ulong lu, ulong luMul, ulong luDiv);
ulong FcmpCompareFracs(long lwNum1, long lwDen1, long lwNum2, long lwDen2);
long LwDivAway(long lwNum, long lwDen);
long LwDivClosest(long lwNum, long lwDen);
long LwRoundAway(long lwSrc, long lwBase);
long LwRoundToward(long lwSrc, long lwBase);
long LwRoundClosest(long lwSrc, long lwBase);
inline long CbRoundToLong(long cb)
{ return (cb + size(long) - 1) & ~(long)(size(long) - 1); }
inline long CbRoundToShort(long cb)
{ return (cb + size(short) - 1) & ~(long)(size(short) - 1); }
inline long CbFromCbit(long cbit)
{ return (cbit + 7) / 8; }
inline byte Fbit(long ibit)
{ return 1 << (ibit & 0x0007); }
inline long IbFromIbit(long ibit)
{ return ibit >> 3; }
long LwGcd(long lw1, long lw2);
ulong LuGcd(ulong lu1, ulong lu2);
bool FAdjustIv(long *piv, long iv, long cvIns, long cvDel);
#ifdef DEBUG
void AssertIn(long lw, long lwMin, long lwLim);
long LwMul(long lw1, long lw2);
#else //!DEBUG
#define AssertIn(lw, lwMin, lwLim)
inline long LwMul(long lw1, long lw2)
{ return lw1 * lw2; }
#endif //!DEBUG
/****************************************
Byte Swapping
****************************************/
//byte order mask
typedef ulong BOM;
void SwapBytesBom(void *pv, BOM bom);
void SwapBytesRgsw(void *psw, long csw);
void SwapBytesRglw(void *plw, long clw);
const BOM bomNil = 0;
const BOM kbomSwapShort = 0x40000000;
const BOM kbomSwapLong = 0xC0000000;
const BOM kbomLeaveShort = 0x00000000;
const BOM kbomLeaveLong = 0x80000000;
/* You can chain up to 16 of these (2 bits each) */
#define BomField(bomNew, bomLast) ((bomNew) | ((bomLast) >> 2))
#ifdef DEBUG
void AssertBomRglw(BOM bom, long cb);
void AssertBomRgsw(BOM bom, long cb);
#else //!DEBUG
#define AssertBomRglw(bom, cb)
#define AssertBomRgsw(bom, cb)
#endif //!DEBUG
/****************************************
OS level rectangle and point
****************************************/
#ifdef MAC
typedef Rect RCS;
typedef Point PTS;
#elif defined(WIN)
typedef RECT RCS;
typedef POINT PTS;
#endif //WIN
/****************************************
Rectangle and point stuff
****************************************/
// options for PT::Transform and RC::Transform
enum
{
fptNil,
fptNegateXp = 1, // negate xp values (and swap them in an RC)
fptNegateYp = 2, // negate yp values (and swap them in an RC)
fptTranspose = 4, // swap xp and yp values (done after negating)
};
class RC;
typedef class RC *PRC;
class PT
{
public:
long xp;
long yp;
public:
//constructors
PT(void) {}
PT(long xpT, long ypT) { xp = xpT, yp = ypT; }
//for assigning to/from a PTS
operator PTS(void);
PT & operator = (PTS &pts);
PT(PTS &pts)
{ *this = pts; }
//interaction with other points
bool operator==(PT &pt)
{ return xp == pt.xp && yp == pt.yp; }
bool operator!=(PT &pt)
{ return xp != pt.xp || yp != pt.yp; }
PT operator+(PT &pt)
{ return PT(xp + pt.xp, yp + pt.yp); }
PT operator-(PT &pt)
{ return PT(xp - pt.xp, yp - pt.yp); }
PT & operator+=(PT &pt)
{ xp += pt.xp; yp += pt.yp; return *this; }
PT & operator-=(PT &pt)
{ xp -= pt.xp; yp -= pt.yp; return *this; }
void Offset(long dxp, long dyp)
{ xp += dxp; yp += dyp; }
//map the point from prcSrc to prcDst coordinates
void Map(RC *prcSrc, RC *prcDst);
PT PtMap(RC *prcSrc, RC *prcDst);
void Transform(ulong grfpt);
};
class RC
{
public:
long xpLeft;
long ypTop;
long xpRight;
long ypBottom;
public:
//constructors
RC(void) {}
RC(long xpLeftT, long ypTopT, long xpRightT, long ypBottomT)
{
AssertThisMem();
xpLeft = xpLeftT;
ypTop = ypTopT;
xpRight = xpRightT;
ypBottom = ypBottomT;
}
//for assigning to/from an RCS
operator RCS(void);
RC & operator = (RCS &rcs);
RC(RCS &rcs)
{ *this = rcs; }
void Zero(void)
{ AssertThisMem(); xpLeft = ypTop = xpRight = ypBottom = 0; }
void Set(long xp1, long yp1, long xp2, long yp2)
{
AssertThisMem();
xpLeft = xp1;
ypTop = yp1;
xpRight = xp2;
ypBottom = yp2;
}
// use klwMin / 2 and klwMax / 2 so Dxp and Dyp are correct
void Max(void)
{
AssertThisMem();
xpLeft = ypTop = klwMin / 2;
xpRight = ypBottom = klwMax / 2;
}
bool FMax(void)
{
AssertThisMem();
return xpLeft == klwMin / 2 && ypTop == klwMin / 2 &&
xpRight == klwMax / 2 && ypBottom == klwMax / 2;
}
//interaction with other rc's and pt's
bool operator==(RC &rc);
bool operator!=(RC &rc);
RC & operator+=(PT &pt)
{
xpLeft += pt.xp;
ypTop += pt.yp;
xpRight += pt.xp;
ypBottom += pt.yp;
return *this;
}
RC & operator-=(PT &pt)
{
xpLeft -= pt.xp;
ypTop -= pt.yp;
xpRight -= pt.xp;
ypBottom -= pt.yp;
return *this;
}
RC operator+(PT &pt)
{
return RC(xpLeft + pt.xp, ypTop + pt.yp,
xpRight + pt.xp, ypBottom + pt.yp);
}
RC operator-(PT &pt)
{
return RC(xpLeft - pt.xp, ypTop - pt.yp,
xpRight - pt.xp, ypBottom - pt.yp);
}
PT PtTopLeft(void)
{ return PT(xpLeft, ypTop); }
PT PtBottomRight(void)
{ return PT(xpRight, ypBottom); }
PT PtTopRight(void)
{ return PT(xpRight, ypTop); }
PT PtBottomLeft(void)
{ return PT(xpLeft, ypBottom); }
//map the rectangle from prcSrc to prcDst coordinates
void Map(RC *prcSrc, RC *prcDst);
void Transform(ulong grfpt);
long Dxp(void)
{ AssertThisMem(); return xpRight - xpLeft; }
long Dyp(void)
{ AssertThisMem(); return ypBottom - ypTop; }
long XpCenter(void)
{ AssertThisMem(); return (xpLeft + xpRight) / 2; }
long YpCenter(void)
{ AssertThisMem(); return (ypTop + ypBottom) / 2; }
bool FEmpty(void)
{ AssertThisMem(); return ypBottom <= ypTop || xpRight <= xpLeft; }
void CenterOnRc(RC *prcBase);
void CenterOnPt(long xp, long yp);
bool FIntersect(RC *prc1, RC *prc2);
bool FIntersect(RC *prc);
bool FPtIn(long xp, long yp);
void InsetCopy(RC *prc, long dxp, long dyp);
void Inset(long dxp, long dyp);
void OffsetCopy(RC *prc, long dxp, long dyp);
void Offset(long dxp, long dyp);
void OffsetToOrigin(void);
void PinPt(PT *ppt);
void PinToRc(RC *prc);
void SqueezeIntoRc(RC *prcBase);
void StretchToRc(RC *prcBase);
void Union(RC *prc1, RC *prc2);
void Union(RC *prc);
long LwArea(void);
bool FContains(RC *prc);
void SetToCell(RC *prcSrc, long crcWidth, long crcHeight,
long ircWidth, long ircHeight);
bool FMapToCell(long xp, long yp, long crcWidth, long crcHeight,
long *pircWidth, long *pircHeight);
};
/****************************************
fractions (ratio/rational)
****************************************/
class RAT
{
ASSERT
private:
long _lwNum;
long _lwDen;
//the third argument of this constructor is bogus. This constructor is
//provided so the GCD calculation can be skipped when we already know
//the numerator and denominator are relatively prime.
RAT(long lwNum, long lwDen, long lwJunk)
{
//lwNum and lwDen are already relatively prime
if (lwDen > 0)
{
_lwNum = lwNum;
_lwDen = lwDen;
}
else
{
_lwNum = -lwNum;
_lwDen = -lwDen;
}
AssertThis(0);
}
public:
//constructors
RAT(void) { _lwDen = 0; }
RAT(long lw) { _lwNum = lw; _lwDen = 1; }
RAT(long lwNum, long lwDen)
{ Set(lwNum, lwDen); }
void Set(long lwNum, long lwDen)
{
long lwGcd = LwGcd(lwNum, lwDen);
if (lwDen < 0)
lwGcd = -lwGcd;
_lwNum = lwNum / lwGcd;
_lwDen = lwDen / lwGcd;
AssertThis(0);
}
//unary minus
RAT operator - (void) const
{ return RAT(-_lwNum, _lwDen, 0); }
//access functions
long LwNumerator(void) { return _lwNum; }
long LwDenominator(void) { return _lwDen; }
long LwAway(void) { return LwDivAway(_lwNum, _lwDen); }
long LwToward(void) { return _lwNum / _lwDen; }
long LwClosest(void) { return LwDivClosest(_lwNum, _lwDen); }
operator long(void)
{ return _lwNum / _lwDen; }
//applying to a long (as a multiplicative operator)
long LwScale(long lw)
{ return (_lwNum != _lwDen) ? LwMulDiv(lw, _lwNum, _lwDen) : lw; }
long LwUnscale(long lw)
{ return (_lwNum != _lwDen) ? LwMulDiv(lw, _lwDen, _lwNum) : lw; }
//operator functions
friend RAT operator + (const RAT &rat1, const RAT &rat2);
friend RAT operator + (const RAT &rat, long lw)
{ return RAT(rat._lwNum + LwMul(rat._lwDen, lw), rat._lwDen); }
friend RAT operator + (long lw, const RAT &rat)
{ return RAT(rat._lwNum + LwMul(rat._lwDen, lw), rat._lwDen); }
friend RAT operator - (const RAT &rat1, const RAT &rat2)
{ return rat1 + (-rat2); }
friend RAT operator - (const RAT &rat, long lw)
{ return RAT(rat._lwNum + LwMul(rat._lwDen, -lw), rat._lwDen); }
friend RAT operator - (long lw, const RAT &rat)
{ return RAT(rat._lwNum + LwMul(rat._lwDen, -lw), rat._lwDen); }
friend RAT operator * (const RAT &rat1, const RAT &rat2)
{
long lwGcd1 = LwGcd(rat1._lwNum, rat2._lwDen);
long lwGcd2 = LwGcd(rat1._lwDen, rat2._lwNum);
return RAT(LwMul(rat1._lwNum / lwGcd1, rat2._lwNum / lwGcd2),
LwMul(rat1._lwDen / lwGcd2, rat2._lwDen / lwGcd1), 0);
}
friend RAT operator * (const RAT &rat, long lw)
{
long lwGcd = LwGcd(rat._lwDen, lw);
return RAT(LwMul(lw / lwGcd, rat._lwNum), rat._lwDen / lwGcd, 0);
}
friend RAT operator * (long lw, const RAT &rat)
{
long lwGcd = LwGcd(rat._lwDen, lw);
return RAT(LwMul(lw / lwGcd, rat._lwNum), rat._lwDen / lwGcd, 0);
}
friend RAT operator / (const RAT &rat1, const RAT &rat2)
{
long lwGcd1 = LwGcd(rat1._lwNum, rat2._lwNum);
long lwGcd2 = LwGcd(rat1._lwDen, rat2._lwDen);
return RAT(LwMul(rat1._lwNum / lwGcd1, rat2._lwDen / lwGcd2),
LwMul(rat1._lwDen / lwGcd2, rat2._lwNum / lwGcd1), 0);
}
friend RAT operator / (const RAT &rat, long lw)
{
long lwGcd = LwGcd(rat._lwNum, lw);
return RAT(rat._lwNum / lwGcd, LwMul(lw / lwGcd, rat._lwDen), 0);
}
friend RAT operator / (long lw, const RAT &rat)
{
long lwGcd = LwGcd(rat._lwNum, lw);
return RAT(LwMul(lw / lwGcd, rat._lwDen), rat._lwNum / lwGcd, 0);
}
friend int operator == (const RAT &rat1, const RAT &rat2)
{ return rat1._lwNum == rat2._lwNum && rat1._lwDen == rat2._lwDen; }
friend int operator == (const RAT &rat, long lw)
{ return rat._lwDen == 1 && rat._lwNum == lw; }
friend int operator == (long lw, const RAT &rat)
{ return rat._lwDen == 1 && rat._lwNum == lw; }
friend int operator != (const RAT &rat1, const RAT &rat2)
{ return rat1._lwNum != rat2._lwNum || rat1._lwDen != rat2._lwDen; }
friend int operator != (const RAT &rat, long lw)
{ return rat._lwDen != 1 || rat._lwNum != lw; }
friend int operator != (long lw, const RAT &rat)
{ return rat._lwDen != 1 || rat._lwNum != lw; }
//operator methods
RAT & operator = (long lw)
{
_lwNum = lw;
_lwDen = 1;
return *this;
}
RAT & operator += (const RAT &rat)
{ *this = *this + rat; return *this; }
RAT & operator += (long lw)
{ *this = *this + lw; return *this; }
RAT & operator -= (const RAT &rat)
{ *this = *this - rat; return *this; }
RAT & operator -= (long lw)
{ *this = *this + (-lw); return *this; }
RAT & operator *= (const RAT &rat)
{ *this = *this * rat; return *this; }
RAT & operator *= (long lw)
{ *this = *this * lw; return *this; }
RAT & operator /= (const RAT &rat)
{ *this = *this / rat; return *this; }
RAT & operator /= (long lw)
{ *this = *this / lw; return *this; }
};
/***************************************************************************
Data versioning utility
***************************************************************************/
struct DVER
{
short _swCur;
short _swBack;
void Set(short swCur, short swBack);
bool FReadable(short swCur, short swMin);
};
#endif //UTILINT_H