home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: WPS_PM
/
WPS_PM.zip
/
npssp181.zip
/
npswpswa.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-10-08
|
16KB
|
449 lines
// Window Animation DLL for NPS WPS Enhancer
// Copyright (C) 1995, N.P.S.
// 100 or more columns are necessary to read this file properly
#define INCL_PM
#include <os2.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include "npswpswa.h"
// to export
extern "C" BOOL EXPENTRY SpinFrame(AnimationData *padat);
extern "C" BOOL EXPENTRY VortexFrames(AnimationData *padat);
extern "C" BOOL EXPENTRY ScatterGatherFrames(AnimationData *padat);
extern "C" BOOL EXPENTRY SpikeFrames(AnimationData *padat);
extern "C" BOOL EXPENTRY FireworksFrames(AnimationData *padat);
const FIXED Fixed1 = 1 << 16;
static POINTL PointZero = { 0, 0 };
static MATRIXLF Matrix1 = { Fixed1, 0, 0, 0, Fixed1, 0, 0, 0, 1 };
void drawBox(HPS hps, POINTL &pointCenter, POINTL &pointRelRightTop);
void drawPolygon(HPS hps, POINTL *paPoints, LONG cPoints);
LONG fixedMul(LONG lMultiplicand, FIXED fMultiplier);
FIXED fixedDiv(LONG lNumerator, LONG lDenominator);
POINTL operator*(const POINTL &point, const MATRIXLF &matrix);
MATRIXLF operator*(const MATRIXLF &matrix1, const MATRIXLF &matrix2);
MATRIXLF mix(const MATRIXLF &matrix1, const MATRIXLF &matrix2, FIXED fMix);
POINTL mix(const POINTL &point1, const POINTL &point2, FIXED fMix);
inline POINTL operator+(POINTL &point1, POINTL &point2)
{ POINTL pointResult;
pointResult.x = point1.x + point2.x;
pointResult.y = point1.y + point2.y;
return pointResult;
}
inline POINTL operator-(POINTL &point1, POINTL &point2)
{ POINTL pointResult;
pointResult.x = point1.x - point2.x;
pointResult.y = point1.y - point2.y;
return pointResult;
}
inline MATRIXLF& operator*=(MATRIXLF &matrix1, const MATRIXLF &matrix2)
{ return matrix1 = matrix1 * matrix2;
}
BOOL EXPENTRY SpinFrame(AnimationData *padat)
{ if (padat->animCallType == AnimationDraw
|| padat->animCallType == AnimationErase)
{ POINTL aPtRectangle[4];
aPtRectangle[1].x = aPtRectangle[0].x = padat->ptRelRightTop.x;
aPtRectangle[1].y = -(aPtRectangle[0].y = padat->ptRelRightTop.y);
MATRIXLF matrix;
FIXED afxScale[2];
afxScale[0] = afxScale[1] = fixedDiv(padat->lStep, padat->cTotalSteps);
GpiScale(padat->hps, &matrix, TRANSFORM_REPLACE, afxScale, &PointZero);
GpiRotate(padat->hps, &matrix, TRANSFORM_ADD,
fixedDiv(padat->lParameter * (padat->lStep - padat->cTotalSteps),
padat->cTotalSteps),
&PointZero);
aPtRectangle[0] = aPtRectangle[0] * matrix;
aPtRectangle[1] = aPtRectangle[1] * matrix;
aPtRectangle[2] = padat->ptCenter + aPtRectangle[0];
aPtRectangle[3] = padat->ptCenter + aPtRectangle[1];
aPtRectangle[0] = padat->ptCenter - aPtRectangle[0];
aPtRectangle[1] = padat->ptCenter - aPtRectangle[1];
drawPolygon(padat->hps, aPtRectangle, 4);
}
return TRUE;
}
BOOL EXPENTRY VortexFrames(AnimationData *padat)
{ switch (padat->animCallType)
{ case AnimationInitialize:
GpiRotate(padat->hps, (MATRIXLF *)padat->achBuffer, TRANSFORM_REPLACE,
72 * Fixed1, &padat->ptCenter);
break;
case AnimationDraw:
case AnimationErase:
{ POINTL ptBoxRel;
ptBoxRel.x = padat->ptRelRightTop.x * padat->lStep / padat->cTotalSteps;
ptBoxRel.y = padat->ptRelRightTop.y * padat->lStep / padat->cTotalSteps;
MATRIXLF matrix;
FIXED afxScale[2];
afxScale[0] = afxScale[1] = fixedDiv((padat->cTotalSteps - padat->lStep) * 4,
padat->cTotalSteps * 3);
GpiTranslate(padat->hps, &matrix, TRANSFORM_REPLACE, &padat->ptRelRightTop);
GpiScale(padat->hps, &matrix, TRANSFORM_ADD, afxScale, &padat->ptCenter);
GpiRotate(padat->hps, &matrix, TRANSFORM_ADD,
fixedDiv(padat->lParameter * padat->lStep, padat->cTotalSteps),
&padat->ptCenter);
POINTL ptBoxCenter = padat->ptCenter * matrix;
for (int iLoop = 0; iLoop < 5; iLoop++)
{ drawBox(padat->hps, ptBoxCenter, ptBoxRel);
ptBoxCenter = ptBoxCenter * *(MATRIXLF *)padat->achBuffer;
}
break;
}
}
return TRUE;
}
BOOL EXPENTRY ScatterGatherFrames(AnimationData *padat)
{ if (padat->animCallType == AnimationDraw
|| padat->animCallType == AnimationErase)
{ LONG lDivisor = padat->lParameter;
POINTL ptBoxRel;
ptBoxRel.x = padat->ptRelRightTop.x * padat->lStep / (padat->cTotalSteps * lDivisor);
ptBoxRel.y = padat->ptRelRightTop.y * padat->lStep / (padat->cTotalSteps * lDivisor);
MATRIXLF matrix;
FIXED afxScale[2];
afxScale[0] = afxScale[1] = fixedDiv(padat->cTotalSteps * 3 - padat->lStep * 2,
padat->cTotalSteps);
GpiScale(padat->hps, &matrix, TRANSFORM_REPLACE, afxScale, &PointZero);
GpiTranslate(padat->hps, &matrix, TRANSFORM_ADD, &padat->ptCenter);
for (int iRow = 0; iRow < lDivisor; iRow++)
{ for (int iColumn = 0; iColumn < padat->lParameter; iColumn++)
{ POINTL ptTileCenter;
ptTileCenter.x = (iRow * 2 - lDivisor + 1) * padat->ptRelRightTop.x / lDivisor;
ptTileCenter.y = (iColumn * 2 - lDivisor + 1) * padat->ptRelRightTop.y / lDivisor;
ptTileCenter = ptTileCenter * matrix;
drawBox(padat->hps, ptTileCenter, ptBoxRel);
}
}
}
return TRUE;
}
BOOL EXPENTRY SpikeFrames(AnimationData *padat)
{ struct SpikeData
{ POINTL aPtTriangleEnd[16][3], aPtEndCenter[16], aPtTriangleCenter[16];
MATRIXLF aMatrixCircle[16];
};
switch (padat->animCallType)
{ case AnimationInitialize:
{ LONG xLeft = padat->rectWindow.xLeft,
xRight = padat->rectWindow.xRight,
yBottom = padat->rectWindow.yBottom,
yTop = padat->rectWindow.yTop;
POINTL *paPtTriangle = ((SpikeData *)padat->achBuffer)->aPtTriangleEnd[0],
*paPtCenter = ((SpikeData *)padat->achBuffer)->aPtEndCenter;
for (int iIndex = 0; iIndex < 16; iIndex++, paPtTriangle += 3, paPtCenter++)
{ paPtTriangle[0] = padat->ptCenter;
if (iIndex < 4)
{ paPtTriangle[1].y = paPtTriangle[2].y = yTop;
paPtTriangle[1].x = (xLeft * (4 - iIndex) + xRight * iIndex) / 4;
paPtTriangle[2].x = (xLeft * (3 - iIndex) + xRight * (iIndex + 1)) / 4;
}
else if (iIndex < 8)
{ paPtTriangle[1].x = paPtTriangle[2].x = xRight;
paPtTriangle[1].y = (yTop * (8 - iIndex) + yBottom * (iIndex - 4)) / 4;
paPtTriangle[2].y = (yTop * (7 - iIndex) + yBottom * (iIndex - 3)) / 4;
}
else if (iIndex < 12)
{ paPtTriangle[1].y = paPtTriangle[2].y = yBottom;
paPtTriangle[1].x = (xRight * (12 - iIndex) + xLeft * (iIndex - 8)) / 4;
paPtTriangle[2].x = (xRight * (11 - iIndex) + xLeft * (iIndex - 7)) / 4;
}
else
{ paPtTriangle[1].x = paPtTriangle[2].x = xLeft;
paPtTriangle[1].y = (yBottom * (16 - iIndex) + yTop * (iIndex - 12)) / 4;
paPtTriangle[2].y = (yBottom * (15 - iIndex) + yTop * (iIndex - 11)) / 4;
}
paPtCenter->x = (paPtTriangle[0].x + paPtTriangle[1].x + paPtTriangle[2].x) / 3;
paPtCenter->y = (paPtTriangle[0].y + paPtTriangle[1].y + paPtTriangle[2].y) / 3;
}
paPtCenter = ((SpikeData *)padat->achBuffer)->aPtTriangleCenter;
POINTL ptTriangleCenter;
ptTriangleCenter.x = padat->ptCenter.x;
ptTriangleCenter.y =
padat->ptCenter.y + (padat->ptRelRightTop.x + padat->ptRelRightTop.y) * 4 / 5;
for (iIndex = 0; iIndex < 16; iIndex++)
{ MATRIXLF matrix;
GpiRotate(padat->hps, &matrix, TRANSFORM_REPLACE,
(33 * Fixed1) + (-22 * Fixed1) * iIndex, &padat->ptCenter);
paPtCenter[iIndex] = ptTriangleCenter * matrix;
POINTL ptTemp =
paPtCenter[iIndex] - ((SpikeData *)padat->achBuffer)->aPtEndCenter[iIndex];
GpiTranslate(padat->hps, &((SpikeData *)padat->achBuffer)->aMatrixCircle[iIndex],
TRANSFORM_REPLACE, &ptTemp);
}
break;
}
case AnimationDraw:
case AnimationErase:
{ POINTL aPtTriangle[3];
FIXED fixedFactor;
MATRIXLF matrix;
FIXED afxScale[2];
afxScale[0] = afxScale[1] = fixedDiv(padat->lStep, padat->cTotalSteps);
if (padat->lStep < padat->cTotalSteps / 2)
{ fixedFactor = (Fixed1 - fixedDiv(padat->lStep * 2, padat->cTotalSteps))
* padat->lParameter;
for (int iIndex = 0; iIndex < 16; iIndex++)
{ GpiScale(padat->hps, &matrix, TRANSFORM_REPLACE, afxScale,
&((SpikeData *)padat->achBuffer)->aPtEndCenter[iIndex]);
GpiRotate(padat->hps, &matrix, TRANSFORM_ADD, fixedFactor,
&((SpikeData *)padat->achBuffer)->aPtEndCenter[iIndex]);
matrix = matrix * ((SpikeData *)padat->achBuffer)->aMatrixCircle[iIndex];
for (int iAngle = 0; iAngle < 3; iAngle++)
{ aPtTriangle[iAngle] =
((SpikeData *)padat->achBuffer)->aPtTriangleEnd[iIndex][iAngle] * matrix;
}
drawPolygon(padat->hps, aPtTriangle, 3);
}
}
else
{ fixedFactor = fixedDiv(padat->lStep * 2 - padat->cTotalSteps, padat->cTotalSteps);
for (int iIndex = 0; iIndex < 16; iIndex++)
{ GpiScale(padat->hps, &matrix, TRANSFORM_REPLACE, afxScale,
&((SpikeData *)padat->achBuffer)->aPtEndCenter[iIndex]);
matrix *= mix(Matrix1, ((SpikeData *)padat->achBuffer)->aMatrixCircle[iIndex],
fixedFactor);
for (int iAngle = 0; iAngle < 3; iAngle++)
{ aPtTriangle[iAngle] =
((SpikeData *)padat->achBuffer)->aPtTriangleEnd[iIndex][iAngle] * matrix;
}
drawPolygon(padat->hps, aPtTriangle, 3);
}
}
break;
}
}
return TRUE;
}
BOOL EXPENTRY FireworksFrames(AnimationData *padat)
{ const int NUMBER_OF_RECTS = 10;
struct FireworksData
{ POINTL aPtCenter[NUMBER_OF_RECTS];
};
switch (padat->animCallType)
{ case AnimationInitialize:
{ POINTL *paPtCenter = ((FireworksData *)padat->achBuffer)->aPtCenter;
POINTL ptRectCenter;
ptRectCenter.x = padat->ptCenter.x;
ptRectCenter.y =
padat->ptCenter.y + (padat->ptRelRightTop.x + padat->ptRelRightTop.y) * 5 / 3;
for (int iIndex = 0; iIndex < NUMBER_OF_RECTS; iIndex++)
{ MATRIXLF matrix;
GpiRotate(padat->hps, &matrix, TRANSFORM_REPLACE,
iIndex * (360 * Fixed1 / NUMBER_OF_RECTS), &padat->ptCenter);
paPtCenter[iIndex] = ptRectCenter * matrix;
}
break;
}
case AnimationDraw:
case AnimationErase:
{ POINTL ptTemp;
FIXED fixedFactor = fixedDiv(padat->lStep, padat->cTotalSteps);
MATRIXLF matrix;
FIXED afxScale[2];
afxScale[0] = afxScale[1] = fixedFactor;
POINTL aPtRect[4], aPtTemp[4];
aPtRect[0].x = aPtRect[3].x = -padat->ptRelRightTop.x;
aPtRect[1].x = aPtRect[2].x = padat->ptRelRightTop.x;
aPtRect[0].y = aPtRect[1].y = padat->ptRelRightTop.y;
aPtRect[2].y = aPtRect[3].y = -padat->ptRelRightTop.y;
for (int iIndex = 0; iIndex < NUMBER_OF_RECTS; iIndex++)
{ GpiScale(padat->hps, &matrix, TRANSFORM_REPLACE, afxScale, &PointZero);
GpiRotate(padat->hps, &matrix, TRANSFORM_ADD,
(Fixed1 - fixedFactor) * padat->lParameter, &PointZero);
POINTL ptTemp;
ptTemp = mix(padat->ptCenter, ((FireworksData *)padat->achBuffer)->aPtCenter[iIndex],
fixedFactor);
GpiTranslate(padat->hps, &matrix, TRANSFORM_ADD, &ptTemp);
for (int iAngle = 0; iAngle < 4; iAngle++)
{ aPtTemp[iAngle] = aPtRect[iAngle] * matrix;
}
drawPolygon(padat->hps, aPtTemp, 4);
}
break;
}
}
return TRUE;
}
// drawing functions
void drawBox(HPS hps, POINTL &ptCenter, POINTL &ptRelRightTop)
{ if (ptRelRightTop.x == 0 && ptRelRightTop.y == 0) return;
POINTL ptTemp = ptCenter - ptRelRightTop;
GpiMove(hps, &ptTemp);
ptTemp = ptCenter + ptRelRightTop;
GpiBox(hps, DRO_OUTLINE, &ptTemp, 0, 0);
}
void drawPolygon(HPS hps, POINTL *paPoints, LONG cPoints)
{ if (cPoints == 0) return;
if (paPoints[cPoints - 1].x == paPoints[0].x
&& paPoints[cPoints - 1].y == paPoints[0].y)
{ return;
}
for (int iIndex = 1; iIndex < cPoints; iIndex++)
{ if (paPoints[iIndex].x == paPoints[iIndex - 1].x
&& paPoints[iIndex].y == paPoints[iIndex - 1].y)
{ return;
}
}
GpiMove(hps, &paPoints[cPoints - 1]);
GpiPolyLine(hps, cPoints, paPoints);
}
// helper functions
LONG fixedMul(LONG lMultiplicand, FIXED fxMultiplier)
{ // returns lMultiplicand * fxMultiplier as a LONG
// also returns a FIXED if lMultiplicand is a FIXED
return lMultiplicand * (fxMultiplier >> 16)
+ (lMultiplicand >> 16) * (fxMultiplier & 0xffff)
+ ((ULONG)((lMultiplicand & 0xffff) * (fxMultiplier & 0xffff)) >> 16);
}
FIXED fixedDiv(LONG lNumerator, LONG lDenominator)
{ // returns lNumerator / lDenominator as a FIXED
// also works well for 2 FIXED's
if (lNumerator == 0 || lDenominator == 0) return 0;
LONG lSignBit = (lNumerator ^ lDenominator) >> 31;
lNumerator = abs(lNumerator);
lDenominator = abs(lDenominator);
ULONG ulQuotient = (ULONG)lNumerator / (ULONG)lDenominator;
lNumerator -= ulQuotient * lDenominator;
if (lNumerator == 0) ulQuotient <<= 16;
else
{ int cShiftRemain = 16;
do
{ ulQuotient <<= 1;
lNumerator <<= 1;
cShiftRemain--;
if (lNumerator >= lDenominator)
{ ulQuotient++;
lNumerator -= lDenominator;
if (lNumerator == 0)
{ ulQuotient <<= cShiftRemain;
break;
}
}
} while (cShiftRemain > 0);
}
return (ulQuotient ^ lSignBit) - lSignBit; /* reverse sign if lSignBit = -1 */
}
POINTL operator*(const POINTL &point, const MATRIXLF &matrix)
{ // returns POINTL transformed by MATRIXLF
POINTL pointResult;
pointResult.x = fixedMul(point.x, matrix.fxM11) + fixedMul(point.y, matrix.fxM21) + matrix.lM31;
pointResult.y = fixedMul(point.x, matrix.fxM12) + fixedMul(point.y, matrix.fxM22) + matrix.lM32;
return pointResult;
}
POINTL mix(const POINTL &pointSource1, const POINTL &pointSource2, FIXED fMix)
{ // mix 2 POINTL's according to FIXED
POINTL pointResult;
pointResult.x = fixedMul(pointSource1.x, fMix) + fixedMul(pointSource2.x, Fixed1 - fMix);
pointResult.y = fixedMul(pointSource1.y, fMix) + fixedMul(pointSource2.y, Fixed1 - fMix);
return pointResult;
}
MATRIXLF operator*(const MATRIXLF &mtx1, const MATRIXLF &mtx2)
{ // returns product of 2 MATRIXLF's
MATRIXLF mtxProduct;
mtxProduct.fxM11 = fixedMul(mtx1.fxM11, mtx2.fxM11) + fixedMul(mtx1.fxM12, mtx2.fxM21);
mtxProduct.fxM12 = fixedMul(mtx1.fxM11, mtx2.fxM12) + fixedMul(mtx1.fxM12, mtx2.fxM22);
mtxProduct.lM13 = 0;
mtxProduct.fxM21 = fixedMul(mtx1.fxM21, mtx2.fxM11) + fixedMul(mtx1.fxM22, mtx2.fxM21);
mtxProduct.fxM22 = fixedMul(mtx1.fxM21, mtx2.fxM12) + fixedMul(mtx1.fxM22, mtx2.fxM22);
mtxProduct.lM23 = 0;
mtxProduct.lM31 = fixedMul(mtx1.lM31, mtx2.fxM11) + fixedMul(mtx1.lM32, mtx2.fxM21) + mtx2.lM31;
mtxProduct.lM32 = fixedMul(mtx1.lM31, mtx2.fxM12) + fixedMul(mtx1.lM32, mtx2.fxM22) + mtx2.lM32;
mtxProduct.lM33 = 1;
return mtxProduct;
}
MATRIXLF mix(const MATRIXLF &matrix1, const MATRIXLF &matrix2, FIXED fMix)
{ // mix 2 MATRIXLF's according to FIXED
MATRIXLF matrixResult;
for (int iIndex = 0; iIndex < 9; iIndex++)
{ ((PLONG)&matrixResult)[iIndex] =
fixedMul(((PLONG)&matrix1)[iIndex], fMix)
+ fixedMul(((PLONG)&matrix2)[iIndex], Fixed1 - fMix);
}
return matrixResult;
}