Files
core/ASCImageStudio3/Common/ImagePaintText2.h

5533 lines
182 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <ImagePaintState.h>
#include <ImageCaching.h>
namespace ImageStudio
{
namespace Paint
{
namespace Text
{
namespace Constants
{
enum ETextFillMode
{
c_nTextFillMode_Normal = 0,
c_nTextFillMode_Letter = 1,
c_nTextFillMode_HorCylinder = 2,
c_nTextFillMode_VerCylinder = 3
};
enum ETextAnimation
{
c_nTextAnim_AlphaSimple = 1, // простой fade на все буквы одновременно
c_nTextAnim_AlphaLetterAZ = 2, // побуквенный fade слева на право
c_nTextAnim_AlphaLetterRandom = 3, // плавный побуквенный fade в случайном порядке
c_nTextAnim_AlphaLetterAZSmooth = 4, // плавный побуквенный fade слева на право
c_nTextAnim_AlphaLetterRandomGlass = 5, // плавный побуквенный fade в случайном порядке c эффектом Лупа
c_nTextAnim_AlphaLetterAZSmoothGlass = 6, // плавный побуквенный fade слева на право с эффектом Лупа
c_nTextAnim_AlphaLetterRandomScale = 7, // плавный побуквенный fade в случайном порядке c увеличением
c_nTextAnim_AlphaLetterAZSmoothScale = 8, // плавный побуквенный fade слева на право с увеличением
c_nTextAnim_AlphaDualToCenter = 80, // плавный побуквенный fade от краёв к центру
c_nTextAnim_AlphaDualFromCenter = 81, // плавный побуквенный fade от центра к краям
c_nTextAnim_DropLeft = 10, // побуквенный drop слева с изменением прозрачности букв
c_nTextAnim_DropTop = 11, // побуквенный drop сверху с изменением прозрачности букв
c_nTextAnim_DropRight = 12, // побуквенный drop справа с изменением прозрачности букв
c_nTextAnim_DropBottom = 13, // побуквенный drop снизу с изменением прозрачности букв
c_nTextAnim_DropTopLeft = 14, // побуквенный drop снизу с изменением прозрачности букв
c_nTextAnim_DropTopRight = 15, // побуквенный drop снизу с изменением прозрачности букв
c_nTextAnim_DropBottomLeft = 16, // побуквенный drop снизу с изменением прозрачности букв
c_nTextAnim_DropBottomRight = 17, // побуквенный drop снизу с изменением прозрачности букв
c_nTextAnim_DropRotate1 = 20, // побуквенный rotate против часовой стрелки с изменением прозрачности букв
c_nTextAnim_DropRotate2 = 21, // побуквенный rotate по часовой стрелке с изменением прозрачности букв
c_nTextAnim_MoveLeft = 30, // движение текста влево
c_nTextAnim_MoveTop = 31, // движение текста вверх
c_nTextAnim_MoveRight = 32, // движение текста вправо
c_nTextAnim_MoveBottom = 33, // движение текста вниз
c_nTextAnim_MoveTopLeft = 34, // движение текста из верхнего левого угла
c_nTextAnim_MoveTopRight = 35, // движение текста из верхнего правого угла
c_nTextAnim_MoveBottomLeft = 36, // движение текста из нижнего левого угла
c_nTextAnim_MoveBottomRight = 37, // движение текста из нижнего правого угла
c_nTextAnim_ScaleFromSmall = 40, // увеличение до нормального размера (с альфой)
c_nTextAnim_ScaleFromLarge = 41, // уменьшение до нормального размера (с альфой)
c_nTextAnim_ScaleFromXLargeYSmall = 42, // уменьшение по Х и увеличение по Y (с альфой)
c_nTextAnim_ScaleFromXSmallYLarge = 43, // увеличение по Х и уменьшение по Y (с альфой)
c_nTextAnim_ScaleFromSmallDropFromTop = 44, // увеличение и падение сверху (с альфой)
c_nTextAnim_ScaleFromSmallDropFromBottom = 45, // увеличение и прилёт снизу (с альфой)
c_nTextAnim_Rotate1 = 50, // вращение по часовой стрелке
c_nTextAnim_Rotate2 = 51, // вращение против часовой стрелки
c_nTextAnim_RotateFromSmall1 = 52, // вращение по часовой стрелке с увеличением
c_nTextAnim_RotateFromSmall2 = 53, // вращение против часовой стрелки с увеличением
c_nTextAnim_RotateFromLarge1 = 54, // вращение по часовой стрелке с уменьшением
c_nTextAnim_RotateFromLarge2 = 55, // вращение против часовой стрелки с уменьшением
c_nTextAnim_StretchScale = 60, // побуквенное расширение
c_nTextAnim_StretchHorScale = 61, // побуквенное расширение по горизонтали
c_nTextAnim_StretchVerScale = 62, // побуквенное расширение по вертикали
c_nTextAnim_StretchLVerScale = 63, // побуквенное сжатие по вертикали
c_nTextAnim_StretchLVerHorScale = 64, // побуквенное растяжение по горизонтали и сжатие по вертикали
c_nTextAnim_StretchSmall = 65, // растяжение по горизонтали с альфой
c_nTextAnim_StretchSmallScale = 66, // растяжение по горизнотали с расширением букв по горизонтали и вертикали
c_nTextAnim_StretchSmallHorScale = 67, // растяжение по горизнотали с расширением по горизонтали
c_nTextAnim_StretchSmallVerScale = 68, // растяжение по горизнотали с расширением букв по вертикали
c_nTextAnim_StretchSmallLargeVerScale = 69, // растяжение по горизнотали с сжатием букв по вертикали
c_nTextAnim_StretchSmallLargeVerHorScale = 70, // растяжение по горизнотали с сжатием букв по вертикали и расширением по горизонтали
c_nTextAnim_StretchLarge = 71, // сжатие по горизонтали с альфой
c_nTextAnim_StretchLargeScale = 72, // сжатие по горизнотали с масштабированием
c_nTextAnim_StretchLargeHorScale = 73, // сжатие по горизнотали с расширением букв по горизонтали
c_nTextAnim_StretchLargeVerScale = 74, // сжатие по горизнотали с расширением букв по вертикали
c_nTextAnim_StretchLargeLargeVerScale = 75, // сжатие по горизнотали с жатием букв по вертикали
c_nTextAnim_StretchLargeLargeVerHorScale = 76, // сжатие по горизнотали с сжатием букв по вертикали и расширением по горизонтали
};
}
namespace Transforms
{
class CMatrix3x3
{
private:
double m[3][3];
BOOL m_bPerspective;
public:
CMatrix3x3()
{
Reset();
};
void Reset()
{
m[0][0] = 1;
m[0][1] = 0;
m[0][2] = 0;
m[1][0] = 0;
m[1][1] = 1;
m[1][2] = 0;
m[2][0] = 0;
m[2][1] = 0;
m[2][2] = 1;
m_bPerspective = FALSE;
}
void SetTranslate( double dX, double dY )
{
m[0][0] = 1;
m[0][1] = 0;
m[0][2] = 0;
m[1][0] = 0;
m[1][1] = 1;
m[1][2] = 0;
m[2][0] = dX;
m[2][1] = dY;
m[2][2] = 1;
m_bPerspective = FALSE;
}
void SetScale( double dScaleX, double dScaleY )
{
m[0][0] = dScaleX;
m[0][1] = 0;
m[0][2] = 0;
m[1][0] = 0;
m[1][1] = dScaleY;
m[1][2] = 0;
m[2][0] = 0;
m[2][1] = 0;
m[2][2] = 1;
m_bPerspective = FALSE;
}
void SetScaleAt( double dScaleX, double dScaleY, double dX, double dY )
{
m[0][0] = dScaleX;
m[0][1] = 0;
m[0][2] = 0;
m[1][0] = 0;
m[1][1] = dScaleY;
m[1][2] = 0;
m[2][0] = dX - dX * dScaleX;
m[2][1] = dY - dY * dScaleY;
m[2][2] = 1;
m_bPerspective = FALSE;
}
void SetRotate( double dAngle /*degrees*/ )
{
dAngle *= IPP_PI180;
double dSin = sin( dAngle );
double dCos = cos( dAngle );
SetRotate( dSin, dCos );
}
void SetRotate( double dSin, double dCos )
{
m[0][0] = dCos;
m[0][1] = -dSin;
m[0][2] = 0;
m[1][0] = dSin;
m[1][1] = dCos;
m[1][2] = 0;
m[2][0] = 0;
m[2][1] = 0;
m[2][2] = 1;
m_bPerspective = FALSE;
}
void SetRotateAt( double dAngle /*degrees*/, double dX, double dY )
{
dAngle *= IPP_PI180;
double dSin = sin( dAngle );
double dCos = cos( dAngle );
SetRotateAt( dSin, dCos, dX, dY );
}
void SetRotateAt( double dSin, double dCos, double dX, double dY )
{
m[0][0] = dCos;
m[0][1] = -dSin;
m[0][2] = 0;
m[1][0] = dSin;
m[1][1] = dCos;
m[1][2] = 0;
m[2][0] = dX - dX * dCos - dY * dSin;
m[2][1] = dY + dX * dSin - dY * dCos;
m[2][2] = 1;
m_bPerspective = FALSE;
}
void SetShear( double dX, double dY )
{
m[0][0] = 1;
m[0][1] = dY;
m[0][2] = 0;
m[1][0] = dX;
m[1][1] = 1;
m[1][2] = 0;
m[2][0] = 0;
m[2][1] = 0;
m[2][2] = 1;
m_bPerspective = FALSE;
}
void SetPerspective( double dX, double dY )
{
m[0][0] = 1;
m[0][1] = 0;
m[0][2] = dX;
m[1][0] = 0;
m[1][1] = 1;
m[1][2] = dY;
m[2][0] = 0;
m[2][1] = 0;
m[2][2] = 1;
m_bPerspective = TRUE;
}
void Translate( double dX, double dY )
{
m[2][0] += m[0][0] * dX + m[1][0] * dY;
m[2][1] += m[0][1] * dX + m[1][1] * dY;
if( !m_bPerspective )
return;
m[2][2] = m[2][2] + m[0][2] * dX + m[1][2] * dY;
}
void Scale( double dScaleX, double dScaleY )
{
m[0][0] *= dScaleX;
m[0][1] *= dScaleX;
m[1][0] *= dScaleY;
m[1][1] *= dScaleY;
if( !m_bPerspective )
return;
m[0][2] *= dScaleX;
m[1][2] *= dScaleY;
}
void ScaleAt( double dScaleX, double dScaleY, double dX, double dY )
{
double x = dX - dX * dScaleX;
double y = dY - dY * dScaleY;
double tmp[6] = {
m[0][0] * dScaleX,
m[0][1] * dScaleX,
m[1][0] * dScaleY,
m[1][1] * dScaleY,
m[0][0] * x + m[1][0] * y + m[2][0],
m[0][1] * x + m[1][1] * y + m[2][1]
};
m[0][0] = tmp[0];
m[0][1] = tmp[1];
m[1][0] = tmp[2];
m[1][1] = tmp[3];
m[2][0] = tmp[4];
m[2][1] = tmp[5];
if( !m_bPerspective )
return;
tmp[0] = m[0][2] * dScaleX;
tmp[1] = m[1][2] * dScaleY;
tmp[2] = m[0][2] * x + m[1][2] * y + m[2][2];
m[0][2] = tmp[0];
m[1][2] = tmp[1];
m[2][2] = tmp[2];
}
void Rotate( double dAngle /*degrees*/ )
{
dAngle *= IPP_PI180;
double dSin = sin( dAngle );
double dCos = cos( dAngle );
Rotate( dSin, dCos );
}
void Rotate( double dSin, double dCos )
{
double tmp[4] = {
m[0][0] * dCos - m[1][0] * dSin,
m[0][1] * dCos - m[1][1] * dSin,
m[0][0] * dSin + m[1][0] * dCos,
m[0][1] * dSin + m[1][1] * dCos
};
m[0][0] = tmp[0];
m[0][1] = tmp[1];
m[1][0] = tmp[2];
m[1][1] = tmp[3];
if( !m_bPerspective )
return;
tmp[0] = m[0][2] * dCos - m[1][2] * dSin;
tmp[1] = m[0][2] * dSin + m[1][2] * dCos;
m[0][2] = tmp[0];
m[1][2] = tmp[1];
}
void RotateAt( double dAngle /*degrees*/, double dX, double dY )
{
dAngle *= IPP_PI180;
double dSin = sin( dAngle );
double dCos = cos( dAngle );
RotateAt( dSin, dCos, dX, dY );
}
void RotateAt( double dSin, double dCos, double dX, double dY )
{
double x = dX - dX * dCos - dY * dSin;
double y = dY + dX * dSin - dY * dCos;
double tmp[6] = {
m[0][0] * dCos - m[1][0] * dSin,
m[0][1] * dCos - m[1][1] * dSin,
m[0][0] * dSin + m[1][0] * dCos,
m[0][1] * dSin + m[1][1] * dCos,
m[0][0] * x + m[1][0] * y + m[2][0],
m[0][1] * x + m[1][1] * y + m[2][1]
};
m[0][0] = tmp[0];
m[0][1] = tmp[1];
m[1][0] = tmp[2];
m[1][1] = tmp[3];
m[2][0] = tmp[4];
m[2][1] = tmp[5];
if( !m_bPerspective )
return;
tmp[0] = m[0][2] * dCos - m[1][2] * dSin;
tmp[1] = m[0][2] * dSin + m[1][2] * dCos;
tmp[2] = m[0][2] * x + m[1][2] * y + m[2][2];
m[0][2] = tmp[0];
m[1][2] = tmp[1];
m[2][2] = tmp[2];
}
void Shear( double dX, double dY )
{
double tmp[4] = {
m[0][0] + m[1][0] * dY,
m[0][1] + m[1][1] * dY,
m[1][0] + m[0][0] * dX,
m[1][1] + m[0][1] * dX
};
m[0][0] = tmp[0];
m[0][1] = tmp[1];
m[1][0] = tmp[2];
m[1][1] = tmp[3];
if( !m_bPerspective )
return;
tmp[0] = m[0][2] + m[1][2] * dY;
tmp[1] = m[1][2] + m[0][2] * dX;
m[0][2] = tmp[0];
m[1][2] = tmp[1];
}
void Perspective( double dX, double dY )
{
m[0][0] += m[2][0] * dX;
m[0][1] += m[2][1] * dX;
m[0][2] += m[2][2] * dX;
m[1][0] += m[2][0] * dY;
m[1][1] += m[2][1] * dY;
m[1][2] += m[2][2] * dY;
m_bPerspective = TRUE;
}
void PreTranslate( double dX, double dY )
{
if( !m_bPerspective )
{
m[2][0] += dX;
m[2][1] += dY;
return;
}
m[0][0] += m[0][2] * dX;
m[0][1] += m[0][2] * dY;
m[1][0] += m[1][2] * dX;
m[1][1] += m[1][2] * dY;
m[2][0] += m[2][2] * dX;
m[2][1] += m[2][2] * dY;
}
static void Multiply( const CMatrix3x3& m1, const CMatrix3x3& m2, CMatrix3x3& result )
{
// result = m1 * m2;
if( m1.m_bPerspective || m2.m_bPerspective )
{
result.m[0][0] = m1.m[0][0] * m2.m[0][0] + m1.m[1][0] * m2.m[0][1] + m1.m[2][0] * m2.m[0][2];
result.m[0][1] = m1.m[0][1] * m2.m[0][0] + m1.m[1][1] * m2.m[0][1] + m1.m[2][1] * m2.m[0][2];
result.m[0][2] = m1.m[0][2] * m2.m[0][0] + m1.m[1][2] * m2.m[0][1] + m1.m[2][2] * m2.m[0][2];
result.m[1][0] = m1.m[0][0] * m2.m[1][0] + m1.m[1][0] * m2.m[1][1] + m1.m[2][0] * m2.m[1][2];
result.m[1][1] = m1.m[0][1] * m2.m[1][0] + m1.m[1][1] * m2.m[1][1] + m1.m[2][1] * m2.m[1][2];
result.m[1][2] = m1.m[0][2] * m2.m[1][0] + m1.m[1][2] * m2.m[1][1] + m1.m[2][2] * m2.m[1][2];
result.m[2][0] = m1.m[0][0] * m2.m[2][0] + m1.m[1][0] * m2.m[2][1] + m1.m[2][0] * m2.m[2][2];
result.m[2][1] = m1.m[0][1] * m2.m[2][0] + m1.m[1][1] * m2.m[2][1] + m1.m[2][1] * m2.m[2][2];
result.m[2][2] = m1.m[0][2] * m2.m[2][0] + m1.m[1][2] * m2.m[2][1] + m1.m[2][2] * m2.m[2][2];
result.m_bPerspective = TRUE;
}
else
{
result.m[0][0] = m1.m[0][0] * m2.m[0][0] + m1.m[1][0] * m2.m[0][1];
result.m[0][1] = m1.m[0][1] * m2.m[0][0] + m1.m[1][1] * m2.m[0][1];
result.m[0][2] = 0;
result.m[1][0] = m1.m[0][0] * m2.m[1][0] + m1.m[1][0] * m2.m[1][1];
result.m[1][1] = m1.m[0][1] * m2.m[1][0] + m1.m[1][1] * m2.m[1][1];
result.m[1][2] = 0;
result.m[2][0] = m1.m[0][0] * m2.m[2][0] + m1.m[1][0] * m2.m[2][1] + m1.m[2][0];
result.m[2][1] = m1.m[0][1] * m2.m[2][0] + m1.m[1][1] * m2.m[2][1] + m1.m[2][1];
result.m[2][2] = 1;
result.m_bPerspective = FALSE;
}
}
void Multiply( const CMatrix3x3& other )
{
CMatrix3x3 tmp( *this );
Multiply( tmp, other, *this );
}
void TransformPoints( Gdiplus::PointF* pPoints, int nCountPoints ) const
{
for( int i = 0; i < nCountPoints; ++i, ++pPoints )
{
double x = pPoints->X * m[0][0] + pPoints->Y * m[1][0] + m[2][0];
double y = pPoints->X * m[0][1] + pPoints->Y * m[1][1] + m[2][1];
if( m_bPerspective )
{
double w = pPoints->X * m[0][2] + pPoints->Y * m[1][2] + m[2][2];
x /= w;
y /= w;
}
pPoints->X = float(x);
pPoints->Y = float(y);
}
}
void GetBounds( const Gdiplus::PointF* pPoints, int nCountPoints, Gdiplus::RectF& result ) const
{
if( nCountPoints <= 0 )
return;
double dMinX = pPoints->X;
double dMaxX = pPoints->X;
double dMinY = pPoints->Y;
double dMaxY = pPoints->Y;
for( int i = 0; i < nCountPoints; ++i, ++pPoints )
{
double x = pPoints->X * m[0][0] + pPoints->Y * m[1][0] + m[2][0];
double y = pPoints->X * m[0][1] + pPoints->Y * m[1][1] + m[2][1];
if( m_bPerspective )
{
double w = pPoints->X * m[0][2] + pPoints->Y * m[1][2] + m[2][2];
x /= w;
y /= w;
}
if( x < dMinX ) dMinX = x;
if( x > dMaxX ) dMaxX = x;
if( y < dMinY ) dMinY = y;
if( y > dMaxY ) dMaxY = y;
}
result.X = float(dMinX);
result.Y = float(dMinY);
result.Width = float(dMaxX - dMinX);
result.Height = float(dMaxY - dMinY);
}
};
class CTimeMarks
{
protected:
double* m_pBuffer;
int m_nCountPoints;
int m_nTotalPoints;
public:
CTimeMarks()
: m_pBuffer( 0 ), m_nCountPoints( 0 ), m_nTotalPoints( 0 )
{
}
CTimeMarks( const CTimeMarks& other )
: m_pBuffer( 0 ), m_nCountPoints( 0 ), m_nTotalPoints( 0 )
{
if( other.m_nCountPoints <= 0 )
return;
int nTotalSize = AlignSize(m_nCountPoints);
double* pNewBuffer = new double[nTotalSize];
if( !pNewBuffer )
return;
memcpy( pNewBuffer, other.m_pBuffer, other.m_nCountPoints * sizeof(double) );
m_pBuffer = pNewBuffer;
m_nCountPoints = other.m_nCountPoints;
m_nTotalPoints = nTotalSize;
}
~CTimeMarks()
{
if( m_pBuffer )
delete [] m_pBuffer;
}
void Clear()
{
if( m_pBuffer )
{
delete [] m_pBuffer;
m_pBuffer = 0;
}
m_nCountPoints = 0;
m_nTotalPoints = 0;
}
const CTimeMarks& operator = (const CTimeMarks& other)
{
if( m_nTotalPoints < other.m_nCountPoints )
{
int nTotalSize = AlignSize( other.m_nCountPoints );
double* pNewBuffer = new double[nTotalSize];
if( !pNewBuffer )
{
// копируем хотя бы часть данных
memcpy( m_pBuffer, other.m_pBuffer, m_nTotalPoints * sizeof(double) );
m_nCountPoints = m_nTotalPoints;
return *this;
}
if( m_pBuffer )
delete [] m_pBuffer;
m_pBuffer = pNewBuffer;
m_nTotalPoints = nTotalSize;
}
if( other.m_nCountPoints > 0 )
{
memcpy( m_pBuffer, other.m_pBuffer, other.m_nCountPoints * sizeof(double) );
}
m_nCountPoints = other.m_nCountPoints;
return *this;
}
BOOL ReservePoints( int nCountPoints )
{
if( m_nCountPoints + nCountPoints > m_nTotalPoints )
{
int nTotalSize = AlignSize( m_nCountPoints + nCountPoints );
double* pNewBuffer = new double[nTotalSize];
if( !pNewBuffer )
return FALSE;
if( m_pBuffer )
{
memcpy( pNewBuffer, m_pBuffer, m_nCountPoints * sizeof(double) );
delete [] m_pBuffer;
}
m_pBuffer = pNewBuffer;
m_nTotalPoints = nTotalSize;
}
return TRUE;
}
BOOL AddPoint( double duration )
{
if( !ReservePoints( 1 ) )
return FALSE;
ApplyPoint( duration );
return TRUE;
}
BOOL AddPoints( double* pPoints, int nCountPoints, int nStride )
{
if( !pPoints )
return FALSE;
if( !ReservePoints( nCountPoints ) )
return FALSE;
while( nCountPoints-- > 0 )
{
ApplyPoint( *pPoints );
pPoints = (double*)(((__int8*)pPoints) + nStride);
}
return TRUE;
}
void RemoveLastPoint()
{
if( m_nCountPoints > 0 )
{
m_nCountPoints -= 1;
}
}
void RemoveLastPoints( int nCountPoints )
{
if( nCountPoints > 0 )
{
m_nCountPoints -= nCountPoints;
if( m_nCountPoints < 0 )
m_nCountPoints = 0;
}
}
int GetCountPoints() const
{
// нулевая временная метка присутствует виртуально,
// поэтому количество меток всегда равно m_nCountPoints + 1
return m_nCountPoints + 1;
}
int GetTotalPoints() const
{
// нулевая временная метка присутствует виртуально,
// поэтому количество меток всегда равно m_nTotalPoints + 1
return m_nTotalPoints + 1;
}
void GetMarks( int& nFirstMark, int& nSecondMark, double& dMarkTime, double dTime ) const
{
nFirstMark = 0;
nSecondMark = 0;
dMarkTime = 0;
if( dTime <= 0 )
return;
if( dTime >= 1 )
{
nFirstMark = m_nCountPoints;
nSecondMark = m_nCountPoints;
dMarkTime = 1;
return;
}
if( m_nCountPoints <= 1 )
{
nSecondMark = m_nCountPoints;
dMarkTime = dTime;
return;
}
dTime *= m_pBuffer[m_nCountPoints - 1];
// TODO: сделать бинарный поиск!
double offset = 0;
for( int nPoint = 0; nPoint < m_nCountPoints; ++nPoint )
{
if( dTime <= m_pBuffer[nPoint] )
{
nFirstMark = nPoint;
nSecondMark = nPoint + 1;
dMarkTime = (dTime - offset) / (m_pBuffer[nPoint] - offset);
return;
}
offset = m_pBuffer[nPoint];
}
}
protected:
static int AlignSize( int size )
{
return size + 3 & ~3;
}
void ApplyPoint( double duration )
{
if( duration < IPP_EPS23 )
duration = IPP_EPS23;
if( duration > IPP_MAX_32S )
duration = IPP_MAX_32S;
if( m_nCountPoints > 0 )
duration += m_pBuffer[m_nCountPoints - 1];
m_pBuffer[m_nCountPoints++] = duration;
}
};
template<typename T>
class CTransforms
{
public:
struct TTransform
{
T transform;
int interpolation;
TTransform()
: transform(),
interpolation( TRUE )
{
}
};
struct TData
{
TTransform data;
double duration;
TData()
: data(), duration( 1 )
{
}
};
private:
CTimeMarks m_oMarks;
TTransform* m_pData;
public:
CTransforms()
: m_oMarks(), m_pData( 0 )
{
}
CTransforms( const CTransforms& other )
: m_oMarks( other.m_oMarks ), m_pData( 0 )
{
CreateBuffer( other.m_pData );
}
~CTransforms()
{
Clear();
}
const CTransforms& operator = (const CTransforms& other)
{
RemoveBuffer();
m_oMarks = other.m_oMarks;
CreateBuffer( other.m_pData );
return this*;
}
void Clear()
{
RemoveBuffer();
m_oMarks.Clear();
}
void AddItems( TData* arrItems, int nCountItems )
{
if( !arrItems && nCountItems <= 0 )
return;
int nSize = m_oMarks.GetCountPoints();
int nMarks = nCountItems;
if( !m_pData )
{
--nSize;
--nMarks;
}
if( m_oMarks.AddPoints( &(arrItems[m_pData ? 0 : 1].duration), nMarks, sizeof(TData)) )
{
TTransform* pBuffer = AllocateBuffer( nSize + nCountItems );
if( pBuffer )
{
if( m_pData )
{
memcpy( pBuffer, m_pData, nSize * sizeof(TTransform) );
FreeBuffer( m_pData );
}
IppiSize bound = {sizeof(TTransform), nCountItems};
ippiCopy_8u_C1R( (Ipp8u*)(&arrItems->data), sizeof(TData), (Ipp8u*)(pBuffer + nSize), sizeof(TTransform), bound );
m_pData = pBuffer;
}
else
{
m_oMarks.RemoveLastPoints( nMarks );
}
}
}
void Interpolate( T& result, double time ) const
{
if( m_pData )
{
int index1 = 0;
int index2 = 0;
m_oMarks.GetMarks( index1, index2, time, time );
TTransform* pItem1 = m_pData + index1;
TTransform* pItem2 = m_pData + index2;
if( pItem2->interpolation && pItem1 != pItem2 )
result.Interpolate( pItem1->transform, pItem2->transform, time );
else
result = pItem2->transform;
}
}
protected:
static TTransform* AllocateBuffer( int nCountItems )
{
return (TTransform*)( new __int64[nCountItems * sizeof(TTransform) >> 3] );
}
static void FreeBuffer( TTransform* pBuffer )
{
delete [] (__int64*)(pBuffer);
}
void RemoveBuffer()
{
if( m_pData )
{
TTransform* pBuffer = m_pData;
int nCountItems = m_oMarks.GetCountPoints();
for( ; nCountItems > 0; --nCountItems, ++pBuffer )
{
pBuffer->~TTransform();
}
FreeBuffer( m_pData );
m_pData = 0;
m_oMarks.RemoveLastPoints( nCountItems );
}
}
BOOL CreateBuffer( TTransform* pOtherBuffer )
{
int nSize = m_oMarks.GetCountPoints();
if( pOtherBuffer && nSize > 0 )
{
m_pData = AllocateBuffer( nSize );
if( m_pData )
{
memcpy( m_pData, pOtherBuffer, nSize * sizeof(TTransform) );
return TRUE;
}
}
m_oMarks.RemoveLastPoints( nSize );
return FALSE;
}
};
class CScale
{
public:
double dScaleX;
double dScaleY;
CScale()
: dScaleX( 1 ), dScaleY( 1 )
{
}
void SetParams( double x, double y )
{
dScaleX = x;
dScaleY = y;
}
void Interpolate( const CScale& src1, const CScale& src2, double time )
{
dScaleX = (src2.dScaleX - src1.dScaleX) * time + src1.dScaleX;
dScaleY = (src2.dScaleY - src1.dScaleY) * time + src1.dScaleY;
}
};
class CScaleAt
{
public:
double dScaleX;
double dScaleY;
double dX;
double dY;
CScaleAt()
: dScaleX( 1 ), dScaleY( 1 ), dX( 0 ), dY( 0 )
{
}
void SetParams( double scaleX, double scaleY, double x, double y )
{
dScaleX = scaleX;
dScaleY = scaleY;
dX = x;
dY = y;
}
void Interpolate( const CScaleAt& src1, const CScaleAt& src2, double time )
{
dScaleX = (src2.dScaleX - src1.dScaleX) * time + src1.dScaleX;
dScaleY = (src2.dScaleY - src1.dScaleY) * time + src1.dScaleY;
dX = (src2.dX - src1.dX) * time + src1.dX;
dY = (src2.dY - src1.dY) * time + src1.dY;
}
};
class CShear
{
public:
double dX;
double dY;
CShear()
: dX( 0 ), dY( 0 )
{
}
void SetParams( double x, double y )
{
dX = x;
dY = y;
}
void Interpolate( const CShear& src1, const CShear& src2, double time )
{
dX = (src2.dX - src1.dX) * time + src1.dX;
dY = (src2.dY - src1.dY) * time + src1.dY;
}
};
class CTranslate
{
public:
double dX;
double dY;
CTranslate()
: dX( 0 ), dY( 0 )
{
}
void SetParams( double x, double y )
{
dX = x;
dY = y;
}
void Interpolate( const CTranslate& src1, const CTranslate& src2, double time )
{
dX = (src2.dX - src1.dX) * time + src1.dX;
dY = (src2.dY - src1.dY) * time + src1.dY;
}
};
class CRotate
{
public:
double dAngle;
CRotate()
: dAngle( 0 )
{
}
void SetParams( double angle )
{
dAngle = angle;
}
void Interpolate( const CRotate& src1, const CRotate& src2, double time )
{
dAngle = (src2.dAngle - src1.dAngle) * time + src1.dAngle;
}
};
class CRotateAt
{
public:
double dAngle;
double dX;
double dY;
CRotateAt()
: dAngle( 0 ), dX( 0 ), dY( 0 )
{
}
void SetParams( double angle, double x, double y )
{
dAngle = angle;
dX = x;
dY = y;
}
void Interpolate( const CRotateAt& src1, const CRotateAt& src2, double time )
{
dAngle = (src2.dAngle - src1.dAngle) * time + src1.dAngle;
dX = (src2.dX - src1.dX) * time + src1.dX;
dY = (src2.dY - src1.dY) * time + src1.dY;
}
};
class CTransparency
{
public:
double dFactor;
CTransparency()
: dFactor( 0 )
{
}
void SetParams( double factor )
{
dFactor = factor;
}
void Interpolate( const CTransparency& src1, const CTransparency& src2, double time )
{
dFactor = (src2.dFactor - src1.dFactor) * time + src1.dFactor;
}
};
class CGeometryTransforms
{
public:
virtual void AddToMatrix( Gdiplus::Matrix& oMatrix, double dTime ) = 0;
virtual void AddToMatrix( CMatrix3x3& oMatrix, double dTime ) = 0;
};
class CScaleTransforms : public CTransforms<CScale>, public CGeometryTransforms
{
public:
virtual void AddToMatrix( Gdiplus::Matrix& oMatrix, double dTime )
{
CScale oScale;
Interpolate( oScale, dTime );
float fx = oScale.dScaleX > 0 ? \
(oScale.dScaleX > IPP_EPS23 ? float(oScale.dScaleX) : IPP_EPS23) : \
(oScale.dScaleX < -IPP_EPS23 ? float(oScale.dScaleX) : -IPP_EPS23);
float fy = oScale.dScaleY > 0 ? \
(oScale.dScaleY > IPP_EPS23 ? float(oScale.dScaleY) : IPP_EPS23) : \
(oScale.dScaleY < -IPP_EPS23 ? float(oScale.dScaleY) : -IPP_EPS23);
oMatrix.Scale( fx, fy, Gdiplus::MatrixOrderAppend );
}
virtual void AddToMatrix( CMatrix3x3& oMatrix, double dTime )
{
CScale oScale;
Interpolate( oScale, dTime );
oMatrix.Scale( oScale.dScaleX, oScale.dScaleY );
}
};
class CScaleAtTransforms : public CTransforms<CScaleAt>, public CGeometryTransforms
{
public:
virtual void AddToMatrix( Gdiplus::Matrix& oMatrix, double dTime )
{
CScaleAt oScale;
Interpolate( oScale, dTime );
float fx = oScale.dScaleX > 0 ? \
(oScale.dScaleX > IPP_EPS23 ? float(oScale.dScaleX) : IPP_EPS23) : \
(oScale.dScaleX < -IPP_EPS23 ? float(oScale.dScaleX) : -IPP_EPS23);
float fy = oScale.dScaleY > 0 ? \
(oScale.dScaleY > IPP_EPS23 ? float(oScale.dScaleY) : IPP_EPS23) : \
(oScale.dScaleY < -IPP_EPS23 ? float(oScale.dScaleY) : -IPP_EPS23);
oMatrix.Translate( Gdiplus::REAL(oScale.dX), Gdiplus::REAL(oScale.dY), Gdiplus::MatrixOrderAppend );
oMatrix.Scale( fx, fy, Gdiplus::MatrixOrderAppend );
oMatrix.Translate( Gdiplus::REAL(-oScale.dX), Gdiplus::REAL(-oScale.dY), Gdiplus::MatrixOrderAppend );
}
virtual void AddToMatrix( CMatrix3x3& oMatrix, double dTime )
{
CScaleAt oScale;
Interpolate( oScale, dTime );
oMatrix.ScaleAt( oScale.dScaleX, oScale.dScaleY, oScale.dX, oScale.dY );
}
};
class CShearTransforms : public CTransforms<CShear>, public CGeometryTransforms
{
public:
virtual void AddToMatrix( Gdiplus::Matrix& oMatrix, double dTime )
{
CShear oShear;
Interpolate( oShear, dTime );
oMatrix.Shear( Gdiplus::REAL(oShear.dX), Gdiplus::REAL(oShear.dY), Gdiplus::MatrixOrderAppend );
}
virtual void AddToMatrix( CMatrix3x3& oMatrix, double dTime )
{
CShear oShear;
Interpolate( oShear, dTime );
oMatrix.Shear( oShear.dX, oShear.dY );
}
};
class CTranslateTransforms : public CTransforms<CTranslate>, public CGeometryTransforms
{
public:
virtual void AddToMatrix( Gdiplus::Matrix& oMatrix, double dTime )
{
CTranslate oTranslate;
Interpolate( oTranslate, dTime );
oMatrix.Translate( Gdiplus::REAL(oTranslate.dX), Gdiplus::REAL(oTranslate.dY), Gdiplus::MatrixOrderAppend );
}
virtual void AddToMatrix( CMatrix3x3& oMatrix, double dTime )
{
CTranslate oTranslate;
Interpolate( oTranslate, dTime );
oMatrix.Translate( oTranslate.dX, oTranslate.dY );
}
};
class CRotateTransforms : public CTransforms<CRotate>, public CGeometryTransforms
{
public:
virtual void AddToMatrix( Gdiplus::Matrix& oMatrix, double dTime )
{
CRotate oRotate;
Interpolate( oRotate, dTime );
oMatrix.Rotate( Gdiplus::REAL(oRotate.dAngle), Gdiplus::MatrixOrderAppend );
}
virtual void AddToMatrix( CMatrix3x3& oMatrix, double dTime )
{
CRotate oRotate;
Interpolate( oRotate, dTime );
oMatrix.Rotate( oRotate.dAngle );
}
};
class CRotateAtTransforms : public CTransforms<CRotateAt>, public CGeometryTransforms
{
public:
virtual void AddToMatrix( Gdiplus::Matrix& oMatrix, double dTime )
{
CRotateAt oRotateAt;
Interpolate( oRotateAt, dTime );
if( abs(oRotateAt.dX) > IPP_EPS23 || abs(oRotateAt.dY) > IPP_EPS23 )
oMatrix.RotateAt( Gdiplus::REAL(oRotateAt.dAngle), Gdiplus::PointF(Gdiplus::REAL(oRotateAt.dX), Gdiplus::REAL(oRotateAt.dY)), Gdiplus::MatrixOrderAppend );
else
oMatrix.Rotate( Gdiplus::REAL(oRotateAt.dAngle) );
}
virtual void AddToMatrix( CMatrix3x3& oMatrix, double dTime )
{
CRotateAt oRotateAt;
Interpolate( oRotateAt, dTime );
oMatrix.RotateAt( oRotateAt.dAngle, oRotateAt.dX, oRotateAt.dY );
}
};
class CTransparencyTransforms : public CTransforms<CTransparency>
{
public:
void AddToFactor( double& factor, double dTime )
{
CTransparency transparency;
Interpolate( transparency, dTime );
factor *= transparency.dFactor;
}
};
class CTransformManager
{
protected:
ATL::CSimpleArray<CGeometryTransforms*> m_arrpGeometryTransforms;
ATL::CSimpleArray<CTransparencyTransforms*> m_arrpTransparencyTransforms;
double m_dTimeOffset;
double m_dTimeDuration;
public:
CTransformManager()
{
m_dTimeOffset = 0;
m_dTimeDuration = 1;
}
~CTransformManager()
{
ReleaseDynamicData();
}
void Clear()
{
m_dTimeOffset = 0;
m_dTimeDuration = 1;
ReleaseDynamicData();
}
void Update( double dTime, Gdiplus::Matrix& oTransform, double& dTransparency )
{
dTime = (dTime - m_dTimeOffset) / m_dTimeDuration;
// выполняем последовательно геометрические трансформации
CGeometryTransforms** pGeometryData = m_arrpGeometryTransforms.GetData();
if( pGeometryData )
{
int nDataSize = m_arrpGeometryTransforms.GetSize();
for( ; nDataSize > 0; --nDataSize, ++pGeometryData )
{
CGeometryTransforms* pTransforms = *pGeometryData;
if( pTransforms )
{
pTransforms->AddToMatrix( oTransform, dTime );
}
}
}
// выполняем последовательно цветовые трансформации
CTransparencyTransforms** pTransparencyData = m_arrpTransparencyTransforms.GetData();
if( pTransparencyData )
{
int nDataSize = m_arrpTransparencyTransforms.GetSize();
for( ; nDataSize > 0; --nDataSize, ++pTransparencyData )
{
CTransparencyTransforms* pTransforms = *pTransparencyData;
if( pTransforms )
{
pTransforms->AddToFactor( dTransparency, dTime );
}
}
}
}
void Update( double dTime, CMatrix3x3& oTransform, double& dTransparency )
{
dTime = (dTime - m_dTimeOffset) / m_dTimeDuration;
// выполняем последовательно геометрические трансформации
CGeometryTransforms** pGeometryData = m_arrpGeometryTransforms.GetData();
if( pGeometryData )
{
int nDataSize = m_arrpGeometryTransforms.GetSize();
for( ; nDataSize > 0; --nDataSize, ++pGeometryData )
{
CGeometryTransforms* pTransforms = *pGeometryData;
if( pTransforms )
{
pTransforms->AddToMatrix( oTransform, dTime );
}
}
}
// выполняем последовательно цветовые трансформации
CTransparencyTransforms** pTransparencyData = m_arrpTransparencyTransforms.GetData();
if( pTransparencyData )
{
int nDataSize = m_arrpTransparencyTransforms.GetSize();
for( ; nDataSize > 0; --nDataSize, ++pTransparencyData )
{
CTransparencyTransforms* pTransforms = *pTransparencyData;
if( pTransforms )
{
pTransforms->AddToFactor( dTransparency, dTime );
}
}
}
}
void SetTimeParams( double offset, double duration )
{
m_dTimeOffset = offset;
m_dTimeDuration = duration > IPP_EPS52 ? duration : 1;
}
void SetTimeParams( double nLetter, double nCountLetters, double dCountActiveLetters )
{
double offset = 0;
double duration = 1;
if( nCountLetters > 1 && dCountActiveLetters > 0 )
{
double factor = (nCountLetters - 1 + dCountActiveLetters);
offset = nLetter / factor;
duration = dCountActiveLetters / factor;
}
m_dTimeOffset = offset;
m_dTimeDuration = duration;
}
CScaleTransforms* CreateScaleTransforms()
{
CScaleTransforms* pTransforms = new CScaleTransforms();
if( pTransforms )
{
if( m_arrpGeometryTransforms.Add( pTransforms ) )
return pTransforms;
delete pTransforms;
}
return NULL;
}
CScaleAtTransforms* CreateScaleAtTransforms()
{
CScaleAtTransforms* pTransforms = new CScaleAtTransforms();
if( pTransforms )
{
if( m_arrpGeometryTransforms.Add( pTransforms ) )
return pTransforms;
delete pTransforms;
}
return NULL;
}
CShearTransforms* CreateShearTransforms()
{
CShearTransforms* pTransforms = new CShearTransforms();
if( pTransforms )
{
if( m_arrpGeometryTransforms.Add( pTransforms ) )
return pTransforms;
delete pTransforms;
}
return NULL;
}
CTranslateTransforms* CreateTranslateTransforms()
{
CTranslateTransforms* pTransforms = new CTranslateTransforms();
if( pTransforms )
{
if( m_arrpGeometryTransforms.Add( pTransforms ) )
return pTransforms;
delete pTransforms;
}
return NULL;
}
CRotateTransforms* CreateRotateTransforms()
{
CRotateTransforms* pTransforms = new CRotateTransforms();
if( pTransforms )
{
if( m_arrpGeometryTransforms.Add( pTransforms ) )
return pTransforms;
delete pTransforms;
}
return NULL;
}
CRotateAtTransforms* CreateRotateAtTransforms()
{
CRotateAtTransforms* pTransforms = new CRotateAtTransforms();
if( pTransforms )
{
if( m_arrpGeometryTransforms.Add( pTransforms ) )
return pTransforms;
delete pTransforms;
}
return NULL;
}
CTransparencyTransforms* CreateTransparencyTransforms()
{
CTransparencyTransforms* pTransforms = new CTransparencyTransforms();
if( pTransforms )
{
if( m_arrpTransparencyTransforms.Add( pTransforms ) )
return pTransforms;
delete pTransforms;
}
return NULL;
}
void AddScaleTransforms( CScaleTransforms::TData* arrTransforms, int nCountTransforms )
{
CScaleTransforms* pTransforms = CreateScaleTransforms();
if( pTransforms )
{
pTransforms->AddItems( arrTransforms, nCountTransforms );
}
}
void AddScaleAtTransforms( CScaleAtTransforms::TData* arrTransforms, int nCountTransforms )
{
CScaleAtTransforms* pTransforms = CreateScaleAtTransforms();
if( pTransforms )
{
pTransforms->AddItems( arrTransforms, nCountTransforms );
}
}
void AddShearTransforms( CShearTransforms::TData* arrTransforms, int nCountTransforms )
{
CShearTransforms* pTransforms = CreateShearTransforms();
if( pTransforms )
{
pTransforms->AddItems( arrTransforms, nCountTransforms );
}
}
void AddTranslateTransforms( CTranslateTransforms::TData* arrTransforms, int nCountTransforms )
{
CTranslateTransforms* pTransforms = CreateTranslateTransforms();
if( pTransforms )
{
pTransforms->AddItems( arrTransforms, nCountTransforms );
}
}
void AddRotateTransforms( CRotateTransforms::TData* arrTransforms, int nCountTransforms )
{
CRotateTransforms* pTransforms = CreateRotateTransforms();
if( pTransforms )
{
pTransforms->AddItems( arrTransforms, nCountTransforms );
}
}
void AddRotateAtTransforms( CRotateAtTransforms::TData* arrTransforms, int nCountTransforms )
{
CRotateAtTransforms* pTransforms = CreateRotateAtTransforms();
if( pTransforms )
{
pTransforms->AddItems( arrTransforms, nCountTransforms );
}
}
void AddTransparencyTransforms( CTransparencyTransforms::TData* arrTransforms, int nCountTransforms )
{
CTransparencyTransforms* pTransforms = CreateTransparencyTransforms();
if( pTransforms )
{
pTransforms->AddItems( arrTransforms, nCountTransforms );
}
}
void AddShear( double x1, double y1, double x2, double y2, BOOL interpolation = TRUE )
{
Text::Transforms::CShearTransforms::TData arrShears[2];
arrShears[0].data.transform.SetParams( x1, y1 );
arrShears[1].data.transform.SetParams( x2, y2 );
arrShears[1].data.interpolation = interpolation;
AddShearTransforms( arrShears, 2 );
}
void AddScale( double dStartScale, double dFinishScale, BOOL interpolation = TRUE )
{
Text::Transforms::CScaleTransforms::TData arrScales[2];
arrScales[0].data.transform.SetParams( dStartScale, dStartScale );
arrScales[1].data.transform.SetParams( dFinishScale, dFinishScale );
arrScales[1].data.interpolation = interpolation;
AddScaleTransforms( arrScales, 2 );
}
void AddScale( double dStartScaleX, double dStartScaleY, double dFinishScaleX, double dFinishScaleY, BOOL interpolation = TRUE )
{
Text::Transforms::CScaleTransforms::TData arrScales[2];
arrScales[0].data.transform.SetParams( dStartScaleX, dStartScaleY );
arrScales[1].data.transform.SetParams( dFinishScaleX, dFinishScaleY );
arrScales[1].data.interpolation = interpolation;
AddScaleTransforms( arrScales, 2 );
}
void AddRotate( double dStartAngle, double dFinishAngle, BOOL interpolation = TRUE )
{
Text::Transforms::CRotateTransforms::TData arrAngles[2];
arrAngles[0].data.transform.SetParams( dStartAngle );
arrAngles[1].data.transform.SetParams( dFinishAngle );
arrAngles[1].data.interpolation = interpolation;
AddRotateTransforms( arrAngles, 2 );
}
void AddRotateAt( double dAngle1, double dAngle2, double dX1, double dY1, double dX2, double dY2, BOOL interpolation = TRUE )
{
Text::Transforms::CRotateAtTransforms::TData arrAngles[2];
arrAngles[0].data.transform.SetParams( dAngle1, dX1, dY1 );
arrAngles[1].data.transform.SetParams( dAngle2, dX2, dY2 );
arrAngles[1].data.interpolation = interpolation;
AddRotateAtTransforms( arrAngles, 2 );
}
void AddRotateAt( double dAngle1, double dAngle2, double dX, double dY, BOOL interpolation = TRUE )
{
Text::Transforms::CRotateAtTransforms::TData arrAngles[2];
arrAngles[0].data.transform.SetParams( dAngle1, dX, dY );
arrAngles[1].data.transform.SetParams( dAngle2, dX, dY );
arrAngles[1].data.interpolation = interpolation;
AddRotateAtTransforms( arrAngles, 2 );
}
void AddTranslate( double x1, double y1, double x2, double y2, BOOL interpolation = TRUE )
{
Text::Transforms::CTranslateTransforms::TData arrMoves[2];
arrMoves[0].data.transform.SetParams( x1, y1 );
arrMoves[1].data.transform.SetParams( x2, y2 );
arrMoves[1].data.interpolation = interpolation;
AddTranslateTransforms( arrMoves, 2 );
}
void AddTransparency( double dStartFactor, double dEndFactor, BOOL interpolation = TRUE )
{
Text::Transforms::CTransparencyTransforms::TData arrFactors[2];
arrFactors[0].data.transform.SetParams( dStartFactor );
arrFactors[1].data.transform.SetParams( dEndFactor );
arrFactors[1].data.interpolation = interpolation;
AddTransparencyTransforms( arrFactors, 2 );
}
void AddFadeTransparency( double dStartFactor, double dEndFactor, double nStartDuration = 1, double nEndDuration = 1 )
{
Text::Transforms::CTransparencyTransforms::TData arrFactors[3];
arrFactors[0].data.transform.SetParams( dStartFactor );
arrFactors[1].data.transform.SetParams( dEndFactor );
arrFactors[2].data.transform.SetParams( dEndFactor );
arrFactors[2].data.interpolation = FALSE;
arrFactors[2].duration = nEndDuration;
arrFactors[1].duration = nStartDuration;
AddTransparencyTransforms( arrFactors, 3 );
}
protected:
void ReleaseDynamicData()
{
// последовательно удаляем геометрические трансформации
CGeometryTransforms** pGeometryData = m_arrpGeometryTransforms.GetData();
if( pGeometryData )
{
int nDataSize = m_arrpGeometryTransforms.GetSize();
for( ; nDataSize > 0; --nDataSize, ++pGeometryData )
{
CGeometryTransforms* pItem = *pGeometryData;
if( pItem )
{
delete pItem;
pItem = NULL;
}
}
m_arrpGeometryTransforms.RemoveAll();
}
// последовательно удаляем цветовые трансформации
CTransparencyTransforms** pTransparencyData = m_arrpTransparencyTransforms.GetData();
if( pTransparencyData )
{
int nDataSize = m_arrpTransparencyTransforms.GetSize();
for( ; nDataSize > 0; --nDataSize, ++pTransparencyData )
{
CTransparencyTransforms* pItem = *pTransparencyData;
if( pItem )
{
delete pItem;
pItem = NULL;
}
}
m_arrpTransparencyTransforms.RemoveAll();
}
}
};
}
namespace Utils
{
enum
{
c_nLeftBound = 0,
c_nTopBound = 1,
c_nRightBound = 2,
c_nBottomBound = 3,
c_nEmptyBound = -1
};
float GetOffsetRect( const Gdiplus::RectF& oLayoutRect, const Gdiplus::RectF& oInnerRect, int nBound )
{
// ============================================================================
// вычисляет смещение внутреннего прямоугольника относительно внешнего так,
// что бы они соприкасались
//
// nBound: 0 - left, 1 - top, 2 - right, 3 - bottom
// ============================================================================
float dMove = 0;
switch( nBound )
{
case c_nLeftBound: dMove = oLayoutRect.X - oInnerRect.X - oInnerRect.Width; break;
case c_nTopBound: dMove = oLayoutRect.Y - oInnerRect.Y - oInnerRect.Height; break;
case c_nRightBound: dMove = oLayoutRect.X - oInnerRect.X + oLayoutRect.Width; break;
case c_nBottomBound: dMove = oLayoutRect.Y - oInnerRect.Y + oLayoutRect.Height; break;
}
return dMove;
}
float GetHorOffsetCenters( const Gdiplus::RectF& oRect1, const Gdiplus::RectF& oRect2 )
{
return oRect2.X - oRect1.X + (oRect2.Width - oRect1.Width)/2;
}
float GetVerOffsetCenters( const Gdiplus::RectF& oRect1, const Gdiplus::RectF& oRect2 )
{
return oRect2.Y - oRect1.Y + (oRect2.Height - oRect1.Height)/2;
}
float GetHorCenter( const Gdiplus::RectF& oRect )
{
return oRect.X + oRect.Width * 0.5f;
}
float GetVerCenter( const Gdiplus::RectF& oRect )
{
return oRect.Y + oRect.Height * 0.5f;
}
Gdiplus::PointF GetCenter( const Gdiplus::RectF& oRect )
{
return Gdiplus::PointF( oRect.X + oRect.Width * 0.5f, oRect.Y + oRect.Height * 0.5f );
}
void ClearRect( Gdiplus::RectF& oRect )
{
oRect.X = oRect.Y = oRect.Width = oRect.Height = 0;
}
void ClearPoint( Gdiplus::PointF& oPoint )
{
oPoint.X = oPoint.Y = 0;
}
void ClearSize( Gdiplus::SizeF& oSize )
{
oSize.Width = oSize.Height = 0;
}
template<typename T>
class ArrayReflection
{
public:
T* ptr;
int count;
ArrayReflection()
: ptr( 0 ), count( 0 )
{
}
ArrayReflection( T* pData, int nCount )
: ptr( pData ), count( nCount )
{
}
ArrayReflection( ATL::CSimpleArray< T >& oArray )
: ptr( oArray.GetData() ), count( oArray.GetSize() )
{
}
ArrayReflection( ATL::CAtlArray< T >& oArray )
: ptr( oArray.GetData() ), count((int)oArray.GetCount() )
{
}
ArrayReflection( ATL::CSimpleArray< T >& oArray, int offset, int size )
: ptr( oArray.GetData() + offset ), count( size )
{
}
ArrayReflection( ATL::CAtlArray< T >& oArray, int offset, int size )
: ptr( oArray.GetData() + offset ), count( size )
{
}
T& operator [](int index)
{
return ptr[index];
}
const T& operator [](int index) const
{
return ptr[index];
}
};
class CPermutator
{
int* m_pValues;
int m_nCount;
public:
CPermutator()
{
m_pValues = NULL;
m_nCount = 0;
}
CPermutator( int nCount, BOOL bPermutate )
{
m_pValues = NULL;
m_nCount = 0;
Create( nCount, bPermutate );
}
virtual ~CPermutator()
{
Destroy();
}
void Destroy()
{
if (NULL != m_pValues)
{
delete[] m_pValues;
m_pValues = NULL;
}
m_nCount = 0;
}
void Create(int nCount, BOOL bPermutate)
{
Destroy();
if (nCount < 1)
return;
m_nCount = nCount;
m_pValues = new int[nCount];
for (int index = 0; index < nCount; ++index)
m_pValues[index] = index;
if (!bPermutate || nCount < 2)
return;
Refresh();
}
void Refresh()
{
for (int index = 0; index < m_nCount; ++index)
{
int nIndexFrom = index;
int nIndexTo = ::rand() % m_nCount;
int nValue1 = m_pValues[nIndexFrom];
int nValue2 = m_pValues[nIndexTo];
m_pValues[nIndexFrom] = nValue2;
m_pValues[nIndexTo] = nValue1;
}
}
int GetCount()
{
return m_nCount;
}
int operator[](int nIndex)
{
//if (nIndex < 0 || nIndex >= m_nCount)
// return -1;
return m_pValues[nIndex];
}
};
}
class CEntity
{
protected:
Gdiplus::Matrix m_oTransform; // текущая трансформация
double m_dTransparency; // текущaя прозрачность
Transforms::CTransformManager m_oPrevTransforms; // менеджер предтрансформаций
Transforms::CTransformManager m_oPostTransforms; // менеджер посттрансформаций
public:
Gdiplus::PointF m_oOrigin; // координаты относительно родителя
Gdiplus::RectF m_oPathBoundRect; // ограничивающий прямоугольник патча без трансформаций
Gdiplus::PointF m_oPathCenter; // координаты центра патча (не обязательно геометрический центр!)
public:
CEntity() : m_dTransparency( 1 )
{
}
CEntity( const CEntity& other )
: m_dTransparency( other.m_dTransparency ),
m_oPrevTransforms( other.m_oPrevTransforms ),
m_oPostTransforms( other.m_oPostTransforms ),
m_oOrigin ( other.m_oOrigin ),
m_oPathBoundRect ( other.m_oPathBoundRect ),
m_oPathCenter ( other.m_oPathCenter )
{
float items[6];
other.m_oTransform.GetElements( items );
m_oTransform.SetElements( items[0], items[1], items[2], items[3], items[4], items[5] );
}
//virtual const CEntity& operator = (const CEntity& other)
//{
// return *this
//}
virtual ~CEntity()
{
}
virtual void Clear()
{
m_oTransform.Reset();
m_dTransparency = 1;
m_oPrevTransforms.Clear();
m_oPostTransforms.Clear();
Utils::ClearPoint( m_oOrigin );
Utils::ClearRect ( m_oPathBoundRect );
Utils::ClearPoint( m_oPathCenter );
}
virtual void Update( double dTime, const Gdiplus::Matrix& oParentTransform, double dParentTransparency )
{
// очищаем текущие значения
m_oTransform.Reset();
m_dTransparency = 1;
// выполняем последовательные трансформации
if( dTime < 1 || dTime > 2 )
{
if( dTime < 2 )
m_oPrevTransforms.Update( dTime, m_oTransform, m_dTransparency );
else
m_oPostTransforms.Update( 3 - dTime, m_oTransform, m_dTransparency );
}
// переносим позицию относительно внешней системы координат
m_oTransform.Translate( m_oOrigin.X, m_oOrigin.Y, Gdiplus::MatrixOrderAppend );
// объединяем с внешними данными
m_oTransform.Multiply( &oParentTransform, Gdiplus::MatrixOrderAppend );
m_dTransparency *= dParentTransparency;
}
const Gdiplus::Matrix& GetTransform() const
{
return m_oTransform;
}
const double GetAlphaFactor() const
{
return m_dTransparency;
}
Transforms::CTransformManager& GetTransformManager( BOOL bPhaseIn )
{
return bPhaseIn ? m_oPrevTransforms : m_oPostTransforms;
}
void RemoveTransforms()
{
m_oPrevTransforms.Clear();
m_oPostTransforms.Clear();
}
};
class CLetterEntity : public CEntity
{
protected:
Gdiplus::RectF m_oLayoutRect; // ограничивающий прямоугольник для патча после применения трансформов
CLetterEntity* m_pNextLetter; // указатель на следующую букву в списке
public:
Gdiplus::GraphicsPath* m_pPath; // указатель на внешний патч. не требует применения new/delete
BOOL m_bNotLetter; // признак линии перечёркивания(подчёркивания) для стилей Strikeout и Underline
public:
CLetterEntity()
{
m_pNextLetter = NULL;
m_pPath = NULL;
m_bNotLetter = FALSE;
}
virtual ~CLetterEntity()
{
ReleaseChildLetter();
}
virtual void Clear()
{
ReleaseChildLetter();
CEntity::Clear();
m_pPath = NULL;
Utils::ClearRect( m_oLayoutRect );
m_bNotLetter = FALSE;
}
virtual void Update( double dTime, const Gdiplus::Matrix& oParentTransform, double dParentTransparency )
{
CEntity::Update( dTime, oParentTransform, dParentTransparency );
// корректируем относительно траектории
m_oTransform.Translate( -m_oPathCenter.X, -m_oPathCenter.Y, Gdiplus::MatrixOrderPrepend );
// расчитываем ограничивающий прямоугольник
if( m_pPath )
{
m_pPath->GetBounds( &m_oLayoutRect, &m_oTransform );
}
}
double GetPathLength( const Gdiplus::GraphicsPath* pSource )
{
if( !pSource )
return 0;
Gdiplus::GraphicsPathIterator iter( pSource );
if( Gdiplus::Ok != iter.GetLastStatus() )
return 0;
double dLength = 0;
Gdiplus::GraphicsPath path;
BOOL bPathClosed;
int nSubPathCount = iter.GetSubpathCount();
if( nSubPathCount > 1 )
{
for( int i = 0; i < nSubPathCount; i++ )
{
if( iter.NextSubpath( &path, &bPathClosed ) )
{
dLength += GetPathLength( &path );
}
}
return dLength;
}
if( !iter.NextSubpath( &path, &bPathClosed ) )
return 0;
path.Outline();
int nPointCount = path.GetPointCount();
if( nPointCount <= 1 )
return 0;
CBuffer<Gdiplus::PointF> oPathPoints( nPointCount + 1 );
if( oPathPoints.IsEmpty() )
return 0;
path.GetPathPoints( oPathPoints.GetPtr(), nPointCount );
if( bPathClosed )
{
oPathPoints[nPointCount++] = oPathPoints[0];
}
for( int i = 1; i < nPointCount; i++ )
{
double dx = oPathPoints[i].X - oPathPoints[i - 1].X;
double dy = oPathPoints[i].Y - oPathPoints[i - 1].Y;
dLength += sqrt( dx * dx + dy * dy );
}
return dLength;
}
void Draw( Gdiplus::Graphics& oRender, const Gdiplus::RectF& oClipRect, Painter::CBrush& oBrush, Painter::CTextureManager* pTextureManager, Gdiplus::RectF* pBoundClip )
{
if( !m_pPath || m_dTransparency < IPP_EPS23 )
return;
Gdiplus::RectF oRenderRect = m_oLayoutRect;
oRenderRect.Inflate( 1, 1 );
if( FALSE == oRenderRect.Intersect( oClipRect ) )
return;
oRender.SetTransform( &m_oTransform );
oBrush.SetTransparency( m_dTransparency );
Gdiplus::Brush* pBrush = oBrush.GetBrush( pTextureManager, pBoundClip );
if( pBrush )
{
oRender.FillPath( pBrush, m_pPath );
}
}
void DrawEdge( Gdiplus::Graphics& oRender, const Gdiplus::RectF& oClipRect, Painter::CEdgeText& oEdge )
{
if( !m_pPath || m_dTransparency < IPP_EPS23 )
return;
float fPenWidth = (float)oEdge.GetDistance();
Gdiplus::RectF oRenderRect = m_oLayoutRect;
oRenderRect.Inflate( 1 + fPenWidth, 1 + fPenWidth );
if( FALSE == oRenderRect.Intersect( oClipRect ) )
return;
oRender.SetTransform( &m_oTransform );
oEdge.SetTransparency( m_dTransparency );
Gdiplus::Pen* pPen = oEdge.GetPen();
if( pPen )
{
oRender.DrawPath( pPen, m_pPath );
}
}
void DrawEdge2( Gdiplus::Graphics& oRender, const Gdiplus::RectF& oClipRect, Painter::CEdgeText& oEdge, double dCompleteness )
{
if( !m_pPath || m_dTransparency < IPP_EPS23 || dCompleteness < IPP_EPS23 )
return;
float fPenWidth = (float)oEdge.GetDistance();
Gdiplus::RectF oRenderRect = m_oLayoutRect;
oRenderRect.Inflate( 1 + fPenWidth, 1 + fPenWidth );
if( FALSE == oRenderRect.Intersect( oClipRect ) )
return;
oEdge.SetTransparency( m_dTransparency );
Gdiplus::Pen* pPen = oEdge.GetPen();
if( !pPen )
return;
if( dCompleteness > (1.0 - IPP_EPS23) )
{
oRender.SetTransform( &m_oTransform );
oRender.DrawPath( pPen, m_pPath );
return;
}
Gdiplus::GraphicsPath path;
path.AddPath( m_pPath, FALSE );
if( path.GetLastStatus() != Gdiplus::Ok )
return;
path.Outline( &m_oTransform );
int nPointCount = path.GetPointCount();
if( nPointCount <= 1 )
return;
CBuffer<Gdiplus::PointF> oPathPoints( nPointCount + 1 );
CBuffer<BYTE> oPathTypes( nPointCount + 1 );
CBuffer<double> oPathLengths( nPointCount + 1 );
if( oPathTypes.IsEmpty() || oPathPoints.IsEmpty() || oPathLengths.IsEmpty() )
return;
path.GetPathPoints( oPathPoints.GetPtr(), nPointCount );
path.GetPathTypes( oPathTypes.GetPtr(), nPointCount );
oPathTypes[nPointCount] = 0;
oPathLengths[0] = 0;
int nStartSubPathIndex = 0;
double dMaxLength = 0;
for( int i = 1; i <= nPointCount; i++ )
{
double dx, dy;
int nPointType = oPathTypes[i] & PathPointTypePathTypeMask;
if( nPointType != PathPointTypeStart )
{
dx = oPathPoints[i].X;
dy = oPathPoints[i].Y;
}
else
{
dx = oPathPoints[nStartSubPathIndex].X;
dy = oPathPoints[nStartSubPathIndex].Y;
nStartSubPathIndex = i;
}
dx -= oPathPoints[i - 1].X;
dy -= oPathPoints[i - 1].Y;
dMaxLength += sqrt( dx * dx + dy * dy );
oPathLengths[i] = dMaxLength;
}
dMaxLength *= dCompleteness;
nStartSubPathIndex = 0;
for( int i = 1; i <= nPointCount; i++ )
{
int nPointType = oPathTypes[i] & PathPointTypePathTypeMask;
if( nPointType != PathPointTypeStart )
{
if( oPathLengths[i] <= dMaxLength )
continue;
double dPercent = (oPathLengths[i] - dMaxLength) / (oPathLengths[i] - oPathLengths[i - 1]);
double x = oPathPoints[i].X;
double y = oPathPoints[i].Y;
oPathPoints[i].X = float(x - (x - oPathPoints[i - 1].X) * dPercent);
oPathPoints[i].Y = float(y - (y - oPathPoints[i - 1].Y) * dPercent);
oRender.ResetTransform();
oRender.DrawLines( pPen, &oPathPoints[nStartSubPathIndex], i - nStartSubPathIndex + 1 );
return;
}
else
{
if( oPathLengths[i] <= dMaxLength )
{
Gdiplus::PointF tmp = oPathPoints[i];
oPathPoints[i] = oPathPoints[nStartSubPathIndex];
oRender.ResetTransform();
oRender.DrawLines( pPen, &oPathPoints[nStartSubPathIndex], i - nStartSubPathIndex + 1 );
oPathPoints[i] = tmp;
nStartSubPathIndex = i;
continue;
}
double dPercent = (oPathLengths[i] - dMaxLength) / (oPathLengths[i] - oPathLengths[i - 1]);
double x = oPathPoints[nStartSubPathIndex].X;
double y = oPathPoints[nStartSubPathIndex].Y;
oPathPoints[i].X = float(x - (x - oPathPoints[i - 1].X) * dPercent);
oPathPoints[i].Y = float(y - (y - oPathPoints[i - 1].Y) * dPercent);
oRender.ResetTransform();
oRender.DrawLines( pPen, &oPathPoints[nStartSubPathIndex], i - nStartSubPathIndex + 1 );
return;
}
}
}
void DrawShadow( Gdiplus::Graphics& oRender, const Gdiplus::RectF& oClipRect, const Gdiplus::Color oColor, float dx, float dy, int nBlurSize )
{
if( !m_pPath || m_dTransparency < IPP_EPS23 )
return;
int nMargin = 5;
Gdiplus::RectF oRenderRect = m_oLayoutRect;
oRenderRect.Inflate( float(nMargin + nBlurSize), float(nMargin + nBlurSize) );
oRenderRect.Offset( dx, dy );
if( FALSE == oRenderRect.Intersect( oClipRect ) )
return;
int w = int(oRenderRect.Width + 0.5f);
int h = int(oRenderRect.Height + 0.5f);
if( w < 1 || h < 1 )
return;
int alpha = int(oColor.GetAlpha() * m_dTransparency + 0.5f);
if( alpha < 0 ) alpha = 0;
if( alpha > 255 ) alpha = 255;
Gdiplus::Color oShadowColor(BYTE(alpha), oColor.GetR(), oColor.GetG(), oColor.GetB());
Gdiplus::SolidBrush oShadowBrush( nBlurSize > 0 ? Gdiplus::Color::Blue : oShadowColor );
Gdiplus::Bitmap oTempBitmap( w, h );
if( true )
{
Gdiplus::Graphics oLocalRender(&oTempBitmap);
oLocalRender.SetTransform( &m_oTransform );
oLocalRender.TranslateTransform( dx-oRenderRect.X, dy-oRenderRect.Y, MatrixOrderAppend );
oLocalRender.SetInterpolationMode(InterpolationModeBilinear);
oLocalRender.SetSmoothingMode(SmoothingModeAntiAlias);
oLocalRender.Clear( Gdiplus::Color(0, 0, 0, 0) );
oLocalRender.FillPath( &oShadowBrush, m_pPath );
}
GDIPLUS_ShadowBlur(oTempBitmap, nBlurSize, oShadowColor.GetValue() );
oRender.DrawImage( &oTempBitmap, oRenderRect.X, oRenderRect.Y );
}
CLetterEntity* AddChildLetter()
{
CLetterEntity* pLetter = new CLetterEntity( *this );
if( pLetter )
{
m_pNextLetter = pLetter;
}
return pLetter;
}
void ReleaseChildLetter()
{
if( m_pNextLetter )
{
m_pNextLetter->ReleaseChildLetter();
delete [] m_pNextLetter;
m_pNextLetter = NULL;
}
}
protected:
static void GDIPLUS_ShadowBlur(Gdiplus::Bitmap& oBitmap, int nBlurSize, DWORD dwShadowColor)
{
if( nBlurSize < 1 )
{
return;
}
Gdiplus::BitmapData oBitmapData;
if( Gdiplus::Ok == oBitmap.LockBits(NULL, Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeWrite, PixelFormat32bppARGB, &oBitmapData) )
{
BGRA_ShadowBlur((BYTE*)oBitmapData.Scan0, oBitmapData.Width, oBitmapData.Height, oBitmapData.Stride, nBlurSize, dwShadowColor);
oBitmap.UnlockBits(&oBitmapData);
}
}
static void BGRA_ShadowBlur( BYTE* pBGRA, int nWidth, int nHeight, int nStride, int nBlurSize, DWORD dwShadowColor )
{
if( !pBGRA || nWidth < 1 || nHeight < 1 || nStride < nWidth*4 || nBlurSize < 1 )
{
return;
}
int nBufStride = nWidth * 4;
BYTE* pBuffer = new BYTE[nBufStride * nHeight];
if( !pBuffer )
{
return;
}
int edge = min(nWidth, nBlurSize);
FillZeroLeftRightEdge( pBuffer, edge, nHeight, nBufStride, nWidth - edge );
BGRA_ShadowBlurVertical(pBGRA, pBuffer, nWidth, nHeight, nStride, nBufStride, nBlurSize);
BGRA_ShadowBlurHorizontal(dwShadowColor, pBuffer, pBGRA, nWidth, nHeight, nBufStride, nStride, nBlurSize);
delete[] pBuffer;
}
static BOOL BGRA_ShadowBlurHorizontal( DWORD dwColor, BYTE* pSrcData, BYTE* pDstData, int nWidth, int nHeight, int nSrcStride, int nDstStride, int nBlurSize )
{
if( !pSrcData || !pDstData || nWidth < 1 || nHeight < 1 || nSrcStride < 1 || nDstStride < 1 || nBlurSize < 1 )
{
return FALSE;
}
int nLength;
int nA, nR, nG, nB;
int nClr;
DWORD nFactor;
DWORD nClrFactor;
DWORD *pSrc, *pDst;
nA = (dwColor >> 24 & 0xff);
nR = (dwColor >> 16 & 0xff);
nG = (dwColor >> 8 & 0xff);
nB = (dwColor >> 0 & 0xff);
nFactor = (nBlurSize << 1) + 1;
nFactor *= nFactor;
for( ; nHeight > 0; --nHeight, pSrcData += nSrcStride, pDstData += nDstStride )
{
pSrc = (DWORD*)pSrcData;
pDst = (DWORD*)pDstData;
nClr = 0;
// подсчёт начальной суммы
nLength = nBlurSize < nWidth ? nBlurSize : nWidth - 1;
for( ; nLength >= 0; --nLength )
{
nClr += pSrc[nLength];
}
// расчёт новых пикселов в строке
nLength = nWidth;
for( ;; )
{
nClrFactor = nClr / nFactor + 1;
dwColor = (nB * nClrFactor >> 8) << 0;
dwColor |= (nG * nClrFactor >> 8) << 8;
dwColor |= (nR * nClrFactor >> 8) << 16;
dwColor |= (nA * nClrFactor >> 8) << 24;
*pDst = dwColor;
// проверка на выход из цикла
if( nLength <= 1 )
{
break;
}
// вычитаем крайнее левое значение
if( nLength <= nWidth - nBlurSize )
{
nClr -= pSrc[-nBlurSize];
}
// переходим на следующий пиксел
--nLength;
++pSrc;
++pDst;
// прибавляем следующее крайнее правое значение
if( nLength > nBlurSize )
{
nClr += pSrc[nBlurSize];
}
}
}
return TRUE;
}
static BOOL BGRA_ShadowBlurVertical(BYTE* pSrcData, BYTE* pDstData, int nWidth, int nHeight, int nSrcStride, int nDstStride, int nBlurSize )
{
if( !pSrcData || !pDstData || nWidth < 1 || nHeight < 1 || nSrcStride < 1 || nDstStride < 1 || nBlurSize < 1 )
{
return FALSE;
}
int nLength;
DWORD nClr;
BYTE *pSrc, *pDst;
pSrcData += nBlurSize*4;
pDstData += nBlurSize*4;
for( nWidth -= nBlurSize*2; nWidth > 0; --nWidth, pSrcData += 4, pDstData += 4 )
{
pSrc = pSrcData;
pDst = pDstData;
nClr = 0;
// подсчёт начальной суммы
nLength = nBlurSize < nHeight ? nBlurSize : nHeight - 1;
for( nLength *= nSrcStride; nLength >= 0; nLength -= nSrcStride )
{
nClr += *(DWORD*)(pSrc + nLength)&0xff;
}
// расчёт новых пикселов в строке
nLength = nHeight;
for( ;; )
{
*(DWORD*)(pDst) = nClr;
// проверка на выход из цикла
if( nLength <= 1 )
{
break;
}
// вычитаем крайнее верхнее значение
if( nLength <= nHeight - nBlurSize )
{
nClr -= *(DWORD*)(pSrc - nBlurSize*nSrcStride)&0xff;
}
// переходим на следующий пиксел
--nLength;
pSrc += nSrcStride;
pDst += nDstStride;
// прибавляем следующее крайнее нижнее значение
if( nLength > nBlurSize )
{
nClr += *(DWORD*)(pSrc + nBlurSize*nSrcStride)&0xff;
}
}
}
return TRUE;
}
static void FillZeroLeftRightEdge( BYTE* pARGBData, int nEdgeWidth, int nEdgeHeight, int nStride, int nOffset )
{
DWORD* pDst;
int nWidth;
for( ; nEdgeHeight > 0; --nEdgeHeight, pARGBData += nStride )
{
pDst = (DWORD*)pARGBData;
for( nWidth = nEdgeWidth; nWidth > 0; --nWidth, ++pDst )
{
pDst[0] = 0;
pDst[nOffset] = 0;
}
}
}
};
typedef Utils::ArrayReflection<CLetterEntity> CRefLetters;
class CTextEntity : public CEntity
{
public:
class CTextLine
{
public:
int m_nFirstLetter; // номер символа в тексте с которого начинается линия
int m_nLength; // количество символов в линии
Gdiplus::RectF m_oPathBoundRect;
CTextLine()
{
m_nFirstLetter = 0;
m_nLength = 0;
}
};
public:
CAtlArray<CLetterEntity> m_arrLetters; // список букв
CAtlArray<CTextEntity::CTextLine> m_arrLines;
public:
CTextEntity()
{
}
virtual void Clear()
{
CEntity::Clear();
m_arrLetters.RemoveAll();
m_arrLines.RemoveAll();
}
virtual void Update( double dTime, const Gdiplus::Matrix& oParentTransform, const float fParentAlphaFactor )
{
CEntity::Update( dTime, oParentTransform, fParentAlphaFactor );
// обходим последовательно все буквы
CRefLetters letters( m_arrLetters );
for( ; letters.count > 0; --letters.count, ++letters.ptr )
{
letters.ptr->Update( dTime, m_oTransform, m_dTransparency );
}
}
};
typedef Utils::ArrayReflection<CTextEntity::CTextLine> CRefLines;
class CTextPainter2 : public ImageStudio::Caching::CCacheItemPointer
{
protected:
CTextEntity* m_pText;
CAtlArray<Gdiplus::GraphicsPath> m_arrPaths;
Gdiplus::RectF m_oLayoutRect;
//Gdiplus::RectF m_oClipRect;
BOOL m_bClipping;
BOOL m_bRotateClipping;
float m_fLineSpacing;
BOOL m_bUnderLine;
double m_dTime; // последняя временная метка обновления
Painter::CBrush m_oFillBrush;
Painter::CEdgeText m_oEdge;
Painter::CShadow m_oShadow;
public:
IUnknown* pImage;
Painter::CTextureManager m_oTextureManager;
int m_nFillMode;
float m_fAngle;
// направление текста в относительных координатах
double m_dStartX;
double m_dStartY;
double m_dEndX;
double m_dEndY;
BOOL m_bFillText;
BOOL m_bDrawEdge;
BOOL m_bDrawShadow;
int m_nTypeWrittingEdge;
public:
CTextPainter2()
{
m_pText = NULL;
m_bClipping = FALSE;
m_bRotateClipping = FALSE;
m_fLineSpacing = 0;
m_bUnderLine = FALSE;
m_dTime = 0;
pImage = NULL;
m_nFillMode = 0;
m_fAngle = 0;
m_dStartX = 0;
m_dStartY = 0;
m_dEndX = 0;
m_dEndY = 0;
m_bFillText = TRUE;
m_bDrawEdge = TRUE;
m_bDrawShadow = TRUE;
m_nTypeWrittingEdge = 0;
}
~CTextPainter2()
{
ReleaseDynamicData();
}
void Clear()
{
ReleaseDynamicData();
Utils::ClearRect( m_oLayoutRect );
m_fLineSpacing = 0;
m_bUnderLine = FALSE;
m_oFillBrush.Clear();
m_oEdge.Clear();
m_oShadow.Clear();
m_nFillMode = 0;
m_fAngle = 0;
m_bFillText = TRUE;
m_bDrawEdge = TRUE;
m_bDrawShadow = TRUE;
m_nTypeWrittingEdge = 0;
}
BOOL CreateText( BSTR bstrText, const Gdiplus::Font& oFont, const Gdiplus::RectF& oClipLayoutRect, int nHorAlign, int nVerAlign, int nPlaceType = 0, int nFrameWidth = 0, int nFrameHeight = 0 )
{
Clear();
if( NULL == bstrText || FALSE == oFont.IsAvailable() )
return FALSE;
// создаём патч всего текста
Gdiplus::FontFamily oFontFamily;
Gdiplus::StringFormat oStrFormat;
Gdiplus::StringAlignment eStrAlign;
Gdiplus::StringAlignment eLineAlign;
Gdiplus::GraphicsPath oTextPath;
if( Gdiplus::Ok != oFont.GetFamily( &oFontFamily ) )
return FALSE;
Gdiplus::RectF oLayoutRect = oClipLayoutRect;
if( abs(oLayoutRect.Width) < IPP_EPS23 ) oLayoutRect.Width = 0;
if( abs(oLayoutRect.Height) < IPP_EPS23 ) oLayoutRect.Height = 0;
// нормализация прямоугольника вывода
if( oLayoutRect.Width < 0 )
{
oLayoutRect.X += oLayoutRect.Width;
oLayoutRect.Width = -oLayoutRect.Width;
}
if( oLayoutRect.Height < 0 )
{
oLayoutRect.Y += oLayoutRect.Height;
oLayoutRect.Height = -oLayoutRect.Height;
}
// задаём прямоугольник отсечения вывода
m_oLayoutRect = oLayoutRect;
switch( nHorAlign )
{
case Gdiplus::StringAlignmentCenter:
eStrAlign = Gdiplus::StringAlignmentCenter; break;
case Gdiplus::StringAlignmentFar:
eStrAlign = Gdiplus::StringAlignmentFar; break;
default:
eStrAlign = Gdiplus::StringAlignmentNear;
}
switch( nVerAlign )
{
case Gdiplus::StringAlignmentCenter:
eLineAlign = Gdiplus::StringAlignmentCenter; break;
case Gdiplus::StringAlignmentFar:
eLineAlign = Gdiplus::StringAlignmentFar; break;
default:
eLineAlign = Gdiplus::StringAlignmentNear;
}
oStrFormat.SetAlignment( eStrAlign );
oStrFormat.SetLineAlignment( eLineAlign );
Gdiplus::PointF oBufSize;
switch( nPlaceType & 0x7fffffff )
{
case 1:
switch( eStrAlign )
{
case Gdiplus::StringAlignmentCenter:
oBufSize.X = oLayoutRect.Width / 2;
break;
case Gdiplus::StringAlignmentFar:
oBufSize.X = oLayoutRect.Width;
break;
default:;
}
oLayoutRect.Width = 0;
m_bClipping = TRUE;
m_bRotateClipping = (nPlaceType & 0x80000000) ? TRUE : FALSE;
break;
case 2:
switch( eStrAlign )
{
case Gdiplus::StringAlignmentCenter:
oBufSize.X = oLayoutRect.Width / 2;
break;
case Gdiplus::StringAlignmentFar:
oBufSize.X = oLayoutRect.Width;
break;
default:;
}
oLayoutRect.Width = 0;
m_bClipping = m_bRotateClipping = (nPlaceType & 0x80000000) ? TRUE : FALSE;
break;
default:
switch( eLineAlign )
{
case Gdiplus::StringAlignmentCenter:
oBufSize.Y = oLayoutRect.Height / 2;
break;
case Gdiplus::StringAlignmentFar:
oBufSize.Y = oLayoutRect.Height;
break;
default:;
}
oLayoutRect.Height = 0;
m_bClipping = m_bRotateClipping = (nPlaceType & 0x80000000) ? TRUE : FALSE;
};
int nFontStyle = oFont.GetStyle();
float fFontSize = oFont.GetSize();
// получаем общий контур текста
if( Gdiplus::Ok != oTextPath.AddString( bstrText, -1, &oFontFamily, nFontStyle, fFontSize, oLayoutRect, &oStrFormat ))
return FALSE;
Gdiplus::Matrix matrix( 1, 0, 0, 1, oBufSize.X, oBufSize.Y );
oTextPath.Transform( &matrix );
// задаём межстрочный интервал
float fFontAscent = oFontFamily.GetCellAscent( nFontStyle );
float fFontDescent = oFontFamily.GetCellDescent( nFontStyle );
float fFontHeight = oFontFamily.GetEmHeight( nFontStyle );
float fFontSpacing = oFontFamily.GetLineSpacing( nFontStyle );
float fSize = fFontSize / fFontHeight;
m_fLineSpacing = fFontSpacing * fSize;
m_bUnderLine = ((nFontStyle & Gdiplus::FontStyleStrikeout)|(nFontStyle & Gdiplus::FontStyleUnderline)) ? TRUE : FALSE;
BOOL bRetValue = CreateLetters( oTextPath );
if( bRetValue )
{
float fHeight = (fFontAscent + fFontDescent) * fSize;
float fOffset = fFontDescent * fSize / 2;
CorrectionLettersPositions( eLineAlign, fHeight, fOffset );
}
//Gdiplus::PointF oLayoutCenter( Utils::GetCenter( m_oLayoutRect ) );
if( nFrameWidth > 0 )
{
m_oLayoutRect.X = 0;
m_oLayoutRect.Width = (float)nFrameWidth;
}
if( nFrameHeight > 0 )
{
m_oLayoutRect.Y = 0;
m_oLayoutRect.Height = (float)nFrameHeight;
}
return bRetValue;
}
BOOL CreateEffects( int nAnimationFadeIn, int nAnimationFadeOut, int nTypeEffects, BOOL bInitRandom = TRUE )
{
RemoveTransforms();
if( bInitRandom )
::srand( ::GetTickCount() );
CreateTransforms( nAnimationFadeIn, TRUE, nTypeEffects );
CreateTransforms( nAnimationFadeOut, FALSE, nTypeEffects );
Update( 0 );
return TRUE;
}
void Draw( double dTime, Gdiplus::Graphics& oRender )
{
if( dTime != m_dTime )
{
Update( dTime );
}
if( !m_pText )
return;
Gdiplus::GraphicsState oRenderState;
Gdiplus::RectF oClipRect;
oRenderState = oRender.Save();
oRender.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);
oRender.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
oRender.SetInterpolationMode(Gdiplus::InterpolationModeBilinear);
if( m_bClipping )
{
if( !m_bRotateClipping || abs(m_fAngle) < 0.001 )
{
oRender.SetClip( m_oLayoutRect, Gdiplus::CombineModeIntersect );
}
else
{
Gdiplus::Matrix matrix(1, 0, 0, 1, 0, 0);
matrix.RotateAt( m_fAngle, Utils::GetCenter( m_oLayoutRect ), Gdiplus::MatrixOrderAppend );
Gdiplus::Region region( m_oLayoutRect );
region.Transform( &matrix );
oRender.SetClip( &region, Gdiplus::CombineModeIntersect );
}
}
oRender.GetClipBounds( &oClipRect );
oRender.ResetTransform();
CRefLetters letters( m_pText->m_arrLetters );
if( m_oShadow.Visible && m_bDrawShadow )
{
int alpha = min(255, max(0, m_oShadow.GetAlpha()));
int color = m_oShadow.GetColor();
int nBlur = (int)m_oShadow.GetBlurSize();
float dx = (float)m_oShadow.GetDistanceX();
float dy = (float)m_oShadow.GetDistanceY();
Gdiplus::Color oColor( alpha, GetRValue(color), GetGValue(color), GetBValue(color) );
for( int i = 0; i < letters.count; i++ )
{
letters.ptr[i].DrawShadow( oRender, oClipRect, oColor, dx, dy, nBlur );
}
}
int nCurLetter = 0;
if( m_oEdge.Visible && m_bDrawEdge )
{
for( int i = 0; i < letters.count; i++ )
{
if( letters.ptr[i].m_bNotLetter )
continue;
switch( m_nTypeWrittingEdge )
{
case 1:
{
double t = m_dTime * letters.count;
if( nCurLetter >= t )
break;
t -= nCurLetter;
if( t >= 1 )
{
letters.ptr[i].DrawEdge( oRender, oClipRect, m_oEdge );
break;
}
letters.ptr[i].DrawEdge2( oRender, oClipRect, m_oEdge, t );
break;
}
break;
case 2:
letters.ptr[i].DrawEdge2( oRender, oClipRect, m_oEdge, m_dTime );
break;
default:
letters.ptr[i].DrawEdge( oRender, oClipRect, m_oEdge );
}
++nCurLetter;
}
}
Gdiplus::RectF oBrushRect( m_pText->m_oPathBoundRect );
for( int i = 0; i < letters.count; i++ )
{
if( letters.ptr[i].m_bNotLetter && m_oEdge.Visible && m_bDrawEdge )
{
switch( m_nTypeWrittingEdge )
{
case 1:
{
double t = m_dTime * letters.count;
if( nCurLetter >= t )
break;
t -= nCurLetter;
if( t >= 1 )
{
letters.ptr[i].DrawEdge( oRender, oClipRect, m_oEdge );
break;
}
letters.ptr[i].DrawEdge2( oRender, oClipRect, m_oEdge, t );
break;
}
break;
case 2:
letters.ptr[i].DrawEdge2( oRender, oClipRect, m_oEdge, m_dTime );
break;
default:
letters.ptr[i].DrawEdge( oRender, oClipRect, m_oEdge );
}
++nCurLetter;
}
if( m_bFillText )
{
if( m_nFillMode != Constants::c_nTextFillMode_Normal )
{
switch( m_nFillMode )
{
case Constants::c_nTextFillMode_Letter:
oBrushRect = letters.ptr[i].m_oPathBoundRect;
break;
case Constants::c_nTextFillMode_HorCylinder:
break;
case Constants::c_nTextFillMode_VerCylinder:
break;
}
}
letters.ptr[i].Draw( oRender, oClipRect, m_oFillBrush, &m_oTextureManager, &oBrushRect );
}
}
oRender.Restore( oRenderState );
}
void SetFillBrush( const Painter::CBrush& oBrush )
{
m_oFillBrush = oBrush;
}
void SetShadow( const Painter::CShadow& oShadow )
{
m_oShadow = oShadow;
}
void SetEdge( const Painter::CEdgeText& oEdge )
{
m_oEdge = oEdge;
}
protected:
void ReleaseDynamicData()
{
m_oTextureManager.Clear();
if( pImage )
{
pImage->Release();
pImage = NULL;
}
m_arrPaths.RemoveAll();
if( m_pText )
{
delete m_pText;
m_pText = NULL;
}
}
void RemoveTransforms()
{
if( !m_pText )
return;
m_pText->RemoveTransforms();
CRefLetters letters( m_pText->m_arrLetters );
for( ; letters.count > 0; --letters.count, ++letters.ptr )
{
letters.ptr->RemoveTransforms();
}
}
void Update( double dFrame )
{
if( m_pText )
{
m_dTime = dFrame;
Gdiplus::Matrix oMatrix(1, 0, 0, 1, 0, 0);
double dStartX = m_dStartX * m_oLayoutRect.Width;
double dStartY = m_dStartY * m_oLayoutRect.Height;
double dEndX = m_dEndX * m_oLayoutRect.Width;
double dEndY = m_dEndY * m_oLayoutRect.Height;
double dAngle = m_fAngle + atan2( dEndY - dStartY, dEndX - dStartX ) * (180 / IPP_PI);
if( abs(dAngle) > 0.001 )
{
oMatrix.RotateAt( float(dAngle), Utils::GetCenter( m_oLayoutRect ), Gdiplus::MatrixOrderAppend );
}
m_pText->Update( dFrame, oMatrix, 1 );
}
}
static void GetBoundRectForLetters( const Gdiplus::RectF& oMaxLayoutRect, Gdiplus::RectF& oResultRect, CLetterEntity* arrLetters, int nCountLetters )
{
float fLeft = oMaxLayoutRect.GetRight();
float fRight = oMaxLayoutRect.GetLeft();
float fTop = oMaxLayoutRect.GetBottom();
float fBottom = oMaxLayoutRect.GetTop();
while( nCountLetters-- > 0 )
{
Gdiplus::RectF& oRect = arrLetters->m_oPathBoundRect;
if( oRect.GetLeft() < fLeft ) fLeft = oRect.GetLeft();
if( oRect.GetRight() > fRight ) fRight = oRect.GetRight();
if( oRect.GetTop() < fTop ) fTop = oRect.GetTop();
if( oRect.GetBottom() > fBottom ) fBottom = oRect.GetBottom();
++arrLetters;
}
oResultRect.X = fLeft;
oResultRect.Y = fTop;
oResultRect.Width = fRight - fLeft;
oResultRect.Height = fBottom - fTop;
}
BOOL CreateLetters( const Gdiplus::GraphicsPath& oTextPath )
{
Gdiplus::GraphicsPathIterator oPathIterator( &oTextPath );
// расчитываем количество символов в тексте, включая линини перечёркивания
size_t nLetters = 0;
int nStartIndex, nEndIndex;
while( oPathIterator.NextMarker( &nStartIndex, &nEndIndex ) > 0 )
{
++nLetters;
}
if( nLetters < 1 )
return FALSE;
// создаём необходимые динамические данные
if( !m_arrPaths.SetCount( nLetters, 0 ) )
return FALSE;
m_pText = new CTextEntity();
if( !m_pText )
return FALSE;
if( !m_pText->m_arrLetters.SetCount( nLetters, 0 ) )
return FALSE;
// задаём геометрические параметры для всего текста
oTextPath.GetBounds( &m_pText->m_oPathBoundRect );
m_pText->m_oPathCenter = Utils::GetCenter( m_pText->m_oPathBoundRect );
m_pText->m_oOrigin = Utils::GetCenter( m_oLayoutRect ); //m_pText->m_oPathCenter;
// задаём геметрические параметры для каждого символа в тексте
oPathIterator.Rewind();
float fPrevLine = 0.5f;
CLetterEntity* pPrevLetter = NULL;
Gdiplus::GraphicsPath* pPath = m_arrPaths.GetData();
CLetterEntity* pLetter = m_pText->m_arrLetters.GetData();
float fBaseY = m_pText->m_oPathBoundRect.Y + (m_pText->m_oPathBoundRect.Height -
ceil(m_pText->m_oPathBoundRect.Height / m_fLineSpacing) * m_fLineSpacing) / 2;
int nCountLines = 0;
for( ; nLetters > 0; --nLetters, ++pLetter, ++pPath )
{
oPathIterator.NextMarker( pPath );
pLetter->m_pPath = pPath;
pPath->SetFillMode( Gdiplus::FillModeWinding ); // даёт значительное ускорение при отрисовке
pPath->GetBounds( &pLetter->m_oPathBoundRect );
pLetter->m_oPathCenter = Utils::GetCenter( pLetter->m_oPathBoundRect );
float dy = (pLetter->m_oPathCenter.Y - fBaseY) / m_fLineSpacing;
float fLine = floor(dy);
dy = m_fLineSpacing * (fLine - dy + 0.5f);
pLetter->m_oPathCenter.Y += dy;
pLetter->m_oOrigin = pLetter->m_oPathCenter - m_pText->m_oOrigin;
pLetter->m_bNotLetter = TRUE;
++nCountLines;
if( fPrevLine != fLine )
{
fPrevLine = fLine;
}
else
{
if( pPrevLetter )
{
pPrevLetter->m_bNotLetter = FALSE;
--nCountLines;
}
}
pPrevLetter = pLetter;
}
// создаём массив текстовых линий
if( m_pText->m_arrLines.SetCount( nCountLines, 0 ) )
{
CTextEntity::CTextLine* pLine = m_pText->m_arrLines.GetData();
int nFirstIndex = 0;
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; ++nLetter )
{
if( letters[nLetter].m_bNotLetter )
{
pLine->m_nFirstLetter = nFirstIndex;
pLine->m_nLength = nLetter - nFirstIndex + 1;
GetBoundRectForLetters( m_pText->m_oPathBoundRect, pLine->m_oPathBoundRect, letters.ptr + nFirstIndex, pLine->m_nLength );
nFirstIndex = nLetter + 1;
++pLine;
}
}
}
// корректируем положение линий перечёркивания
if( !m_bUnderLine )
{
CRefLetters letters( m_pText->m_arrLetters );
for( ; letters.count > 0; --letters.count, ++letters.ptr )
{
letters.ptr->m_bNotLetter = FALSE;
}
}
return TRUE;
}
void CorrectionLettersPositions( int nVerAlign, float fLineHeight, float fOffsetY )
{
CRefLines lines( m_pText->m_arrLines );
float fTop = +1000000;
float fBottom = -1000000;
float fStart = 0;
float factor = fLineHeight - m_fLineSpacing;
float offset = 0;
switch( nVerAlign )
{
case Gdiplus::StringAlignmentFar:
fStart = m_oLayoutRect.GetBottom();
offset = fOffsetY + factor;
break;
case Gdiplus::StringAlignmentCenter:
fStart = Utils::GetVerCenter( m_oLayoutRect );
offset = fOffsetY / 2;
break;
default:
fStart = m_oLayoutRect.GetTop();
offset = 0;
}
for( int nLine = 0; nLine < lines.count; nLine++ )
{
float pos = floor( (Utils::GetVerCenter( lines[nLine].m_oPathBoundRect ) - fStart) / m_fLineSpacing );
float disp = pos * factor + offset;
Gdiplus::Matrix matrix( 1, 0, 0, 1, 0, disp );
CRefLetters letters( m_pText->m_arrLetters, lines[nLine].m_nFirstLetter, lines[nLine].m_nLength );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
pLetter->m_oOrigin.Y += disp;
pLetter->m_oPathBoundRect.Y += disp;
pLetter->m_oPathCenter.Y += disp;
pLetter->m_pPath->Transform( &matrix );
if( pLetter->m_oPathBoundRect.GetTop() < fTop )
fTop = pLetter->m_oPathBoundRect.GetTop();
if( pLetter->m_oPathBoundRect.GetBottom() > fBottom )
fBottom = pLetter->m_oPathBoundRect.GetBottom();
}
}
m_pText->m_oPathBoundRect.Y = fTop;
m_pText->m_oPathBoundRect.Height = fBottom - fTop;
}
void CreateTransforms( int nId, BOOL bPhaseIn, int nTypeEffects )
{
if( !m_pText )
return;
if( m_pText->m_arrLetters.GetCount() < 1 )
return;
if( 0 == nTypeEffects )
{
switch( nId )
{
case Constants::c_nTextAnim_AlphaSimple:
SetAnimationAlphaBlendSimple( bPhaseIn );
break;
case Constants::c_nTextAnim_AlphaLetterAZ:
SetAnimationAlphaBlendLetterAZ( bPhaseIn );
break;
case Constants::c_nTextAnim_AlphaLetterRandom:
SetAnimationAlphaBlendLetterRandom( bPhaseIn, TRUE, FALSE );
break;
case Constants::c_nTextAnim_AlphaLetterAZSmooth:
SetAnimationAlphaBlendLetterRandom( bPhaseIn, FALSE, FALSE );
break;
case Constants::c_nTextAnim_AlphaLetterRandomGlass:
SetAnimationAlphaBlendLetterRandomGlass( bPhaseIn, TRUE );
break;
case Constants::c_nTextAnim_AlphaLetterAZSmoothGlass:
SetAnimationAlphaBlendLetterRandomGlass( bPhaseIn, FALSE );
break;
case Constants::c_nTextAnim_AlphaLetterRandomScale:
SetAnimationAlphaBlendLetterRandom( bPhaseIn, TRUE, TRUE );
break;
case Constants::c_nTextAnim_AlphaLetterAZSmoothScale:
SetAnimationAlphaBlendLetterRandom( bPhaseIn, FALSE, TRUE );
break;
case Constants::c_nTextAnim_DropLeft:
SetAnimationMove( bPhaseIn, TRUE, -1, 0 );
break;
case Constants::c_nTextAnim_DropTop:
SetAnimationMove( bPhaseIn, TRUE, 0, -1 );
break;
case Constants::c_nTextAnim_DropRight:
SetAnimationMove( bPhaseIn, TRUE, 1, 0 );
break;
case Constants::c_nTextAnim_DropBottom:
SetAnimationMove( bPhaseIn, TRUE, 0, 1 );
break;
case Constants::c_nTextAnim_DropTopLeft:
SetAnimationMove( bPhaseIn, TRUE, -1, -1 );
break;
case Constants::c_nTextAnim_DropTopRight:
SetAnimationMove( bPhaseIn, TRUE, 1, -1 );
break;
case Constants::c_nTextAnim_DropBottomLeft:
SetAnimationMove( bPhaseIn, TRUE, -1, 1 );
break;
case Constants::c_nTextAnim_DropBottomRight:
SetAnimationMove( bPhaseIn, TRUE, -1, -1 );
break;
case Constants::c_nTextAnim_MoveLeft:
SetAnimationMove( bPhaseIn, FALSE, -1, 0 );
break;
case Constants::c_nTextAnim_MoveTop:
SetAnimationMove( bPhaseIn, FALSE, 0, -1 );
break;
case Constants::c_nTextAnim_MoveRight:
SetAnimationMove( bPhaseIn, FALSE, 1, 0 );
break;
case Constants::c_nTextAnim_MoveBottom:
SetAnimationMove( bPhaseIn, FALSE, 0, 1 );
break;
case Constants::c_nTextAnim_MoveTopLeft:
SetAnimationMove( bPhaseIn, FALSE, -1, -1 );
break;
case Constants::c_nTextAnim_MoveTopRight:
SetAnimationMove( bPhaseIn, FALSE, 1, -1 );
break;
case Constants::c_nTextAnim_MoveBottomLeft:
SetAnimationMove( bPhaseIn, FALSE, -1, 1 );
break;
case Constants::c_nTextAnim_MoveBottomRight:
SetAnimationMove( bPhaseIn, FALSE, 1, 1 );
break;
case Constants::c_nTextAnim_DropRotate1:
SetAnimationDropRotate( bPhaseIn, FALSE, TRUE );
break;
case Constants::c_nTextAnim_DropRotate2:
SetAnimationDropRotate( bPhaseIn, TRUE, TRUE );
break;
case Constants::c_nTextAnim_ScaleFromSmall:
SetAnimationScaleFrom( bPhaseIn, TRUE );
break;
case Constants::c_nTextAnim_ScaleFromLarge:
SetAnimationScaleFrom( bPhaseIn, FALSE );
break;
case Constants::c_nTextAnim_ScaleFromXLargeYSmall:
SetAnimationScaleFromXY( bPhaseIn, FALSE );
break;
case Constants::c_nTextAnim_ScaleFromXSmallYLarge:
SetAnimationScaleFromXY( bPhaseIn, TRUE );
break;
case Constants::c_nTextAnim_ScaleFromSmallDropFromTop:
SetAnimationScaleFrom( bPhaseIn, TRUE, -1 );
break;
case Constants::c_nTextAnim_ScaleFromSmallDropFromBottom:
SetAnimationScaleFrom( bPhaseIn, TRUE, 1 );
break;
case Constants::c_nTextAnim_Rotate1:
SetAnimationRotate( bPhaseIn, TRUE );
break;
case Constants::c_nTextAnim_Rotate2:
SetAnimationRotate( bPhaseIn, FALSE );
break;
case Constants::c_nTextAnim_RotateFromSmall1:
SetAnimationRotate( bPhaseIn, TRUE, 1 );
break;
case Constants::c_nTextAnim_RotateFromSmall2:
SetAnimationRotate( bPhaseIn, FALSE, 1 );
break;
case Constants::c_nTextAnim_RotateFromLarge1:
SetAnimationRotate( bPhaseIn, TRUE, -1 );
break;
case Constants::c_nTextAnim_RotateFromLarge2:
SetAnimationRotate( bPhaseIn, FALSE, -1 );
break;
case Constants::c_nTextAnim_StretchScale:
SetAnimationStretchScale( bPhaseIn, 1, 1 );
break;
case Constants::c_nTextAnim_StretchHorScale:
SetAnimationStretchScale( bPhaseIn, 1, 0 );
break;
case Constants::c_nTextAnim_StretchVerScale:
SetAnimationStretchScale( bPhaseIn, 0, 1 );
break;
case Constants::c_nTextAnim_StretchLVerScale:
SetAnimationStretchScale( bPhaseIn, 0, -1 );
break;
case Constants::c_nTextAnim_StretchLVerHorScale:
SetAnimationStretchScale( bPhaseIn, 1, -1 );
break;
case Constants::c_nTextAnim_StretchSmall:
SetAnimationStretchScaleMove( bPhaseIn, TRUE );
break;
case Constants::c_nTextAnim_StretchSmallScale:
SetAnimationStretchScaleMove2( bPhaseIn, TRUE );
break;
case Constants::c_nTextAnim_StretchSmallHorScale:
SetAnimationStretchScaleMove3( bPhaseIn, -1, 0, TRUE );
break;
case Constants::c_nTextAnim_StretchSmallVerScale:
SetAnimationStretchScaleMove3( bPhaseIn, 0, -1, TRUE );
break;
case Constants::c_nTextAnim_StretchSmallLargeVerScale:
SetAnimationStretchScaleMove3( bPhaseIn, 0, 1, TRUE );
break;
case Constants::c_nTextAnim_StretchSmallLargeVerHorScale:
SetAnimationStretchScaleMove3( bPhaseIn, -1, 1, TRUE );
break;
case Constants::c_nTextAnim_StretchLarge:
SetAnimationStretchScaleMove( bPhaseIn, FALSE );
break;
case Constants::c_nTextAnim_StretchLargeScale:
SetAnimationStretchScaleMove2( bPhaseIn, FALSE );
break;
case Constants::c_nTextAnim_StretchLargeHorScale:
SetAnimationStretchScaleMove3( bPhaseIn, -1, 0, FALSE );
break;
case Constants::c_nTextAnim_StretchLargeVerScale:
SetAnimationStretchScaleMove3( bPhaseIn, 0, -1, FALSE );
break;
case Constants::c_nTextAnim_StretchLargeLargeVerScale:
SetAnimationStretchScaleMove3( bPhaseIn, 0, 1, FALSE );
break;
case Constants::c_nTextAnim_StretchLargeLargeVerHorScale:
SetAnimationStretchScaleMove3( bPhaseIn, -1, 1, FALSE );
break;
// дополнение набора
// Appear Displace
case 91: RandomMovements( bPhaseIn ); break;
case 92: AppearFade( bPhaseIn ); break;
case 93: AppearShade( bPhaseIn ); break;
case 94: AppearRotate( bPhaseIn ); break;
case 95: AppearRandom( bPhaseIn ); break;
case 96: Airport( bPhaseIn ); break;
case 97: AppearShake( bPhaseIn ); break;
case 98: AppearWedge( bPhaseIn ); break;
case 99: AppearStream( bPhaseIn ); break;
// Appear Waves
case 101: WaveSimple( bPhaseIn ); break;
case 102: WaveZoom( bPhaseIn ); break;
case 103: WaveFall( bPhaseIn ); break;
case 104: WaveRunShift( bPhaseIn ); break;
case 105: WaveSwing( bPhaseIn ); break;
case 106: WaveRun( bPhaseIn ); break;
case 107: WaveZoomVertical( bPhaseIn ); break;
case 108: WaveShift( bPhaseIn ); break;
case 109: WavePulse( bPhaseIn ); break;
// New
case 402: Ejection( bPhaseIn ); break;
case 403: Ellipse( bPhaseIn ); break;
case 404: Wheel( bPhaseIn ); break;
case 405: Miscarry( bPhaseIn ); break;
case 406: Rotation( bPhaseIn ); break;
case 407: Increase( bPhaseIn ); break;
case 408: TwoString( bPhaseIn ); break;
case 409: Tumbling( bPhaseIn ); break;
case 410: Leave( bPhaseIn ); break;
case 411: Unfold( bPhaseIn ); break;
case 412: Centrifuge( bPhaseIn ); break;
case 413: HorizontalRotation( bPhaseIn ); break;
case 414: HorizontalRotation3D( bPhaseIn ); break;
case 415: VerticalRotation( bPhaseIn ); break;
case 416: CheChe( bPhaseIn ); break;
// New2
case 601: Boomerang( bPhaseIn ); break;
case 602: Flash( bPhaseIn ); break;
case 603: Flight( bPhaseIn ); break;
case 604: Jump( bPhaseIn ); break;
case 605: Compress( bPhaseIn ); break;
case 606: Motion( bPhaseIn ); break;
case 607: Manifestation( bPhaseIn ); break;
case 608: Shot( bPhaseIn ); break;
case 609: Reduction( bPhaseIn ); break;
case 610: VHRotation( bPhaseIn ); break;
case 611: Rotate3D( bPhaseIn ); break;
case 612: Spiral( bPhaseIn ); break;
case 613: Flag( bPhaseIn ); break;
case 614: Perpendicular( bPhaseIn ); break;
case 615: Clock( bPhaseIn ); break;
// New3
case 801: Galaxy( bPhaseIn ); break;
case 802: WaveRotate3D( bPhaseIn ); break;
case 803: RandomJump( bPhaseIn ); break;
case 804: Galaxy2( bPhaseIn ); break;
case 805: Roll( bPhaseIn ); break;
case 806: Conga( bPhaseIn ); break;
case 807: _Matrix( bPhaseIn ); break;
case 808: HotPinkSpin( bPhaseIn ); break;
case 809: HopInJumpOut( bPhaseIn ); break;
case 810: ConJoin( bPhaseIn ); break;
case 811: HopsCotch( bPhaseIn ); break;
case 812: Twist( bPhaseIn ); break;
case 813: StarWars( bPhaseIn ); break;
case 814: Squeeze( bPhaseIn ); break;
case 815: Terminator( bPhaseIn ); break;
}
}
else if( 1 == nTypeEffects )
{
switch( nId )
{
// Appear Displace
case 1: RandomMovements( bPhaseIn ); break;
case 2: AppearFade( bPhaseIn ); break;
case 3: AppearShade( bPhaseIn ); break;
case 4: AppearRotate( bPhaseIn ); break;
case 5: AppearRandom( bPhaseIn ); break;
case 6: Airport( bPhaseIn ); break;
case 7: AppearShake( bPhaseIn ); break;
case 8: AppearWedge( bPhaseIn ); break;
case 9: AppearStream( bPhaseIn ); break;
// Appear Waves
case 101: WaveSimple( bPhaseIn ); break;
case 102: WaveZoom( bPhaseIn ); break;
case 103: WaveFall( bPhaseIn ); break;
case 104: WaveRunShift( bPhaseIn ); break;
case 105: WaveSwing( bPhaseIn ); break;
case 106: WaveRun( bPhaseIn ); break;
case 107: WaveZoomVertical( bPhaseIn ); break;
case 108: WaveShift( bPhaseIn ); break;
case 109: WavePulse( bPhaseIn ); break;
// New
case 402: Ejection( bPhaseIn ); break;
case 403: Ellipse( bPhaseIn ); break;
case 404: Wheel( bPhaseIn ); break;
case 405: Miscarry( bPhaseIn ); break;
case 406: Rotation( bPhaseIn ); break;
case 407: Increase( bPhaseIn ); break;
case 408: TwoString( bPhaseIn ); break;
case 409: Tumbling( bPhaseIn ); break;
case 410: Leave( bPhaseIn ); break;
case 411: Unfold( bPhaseIn ); break;
case 412: Centrifuge( bPhaseIn ); break;
case 413: HorizontalRotation( bPhaseIn ); break;
case 414: HorizontalRotation3D( bPhaseIn ); break;
case 415: VerticalRotation( bPhaseIn ); break;
case 416: CheChe( bPhaseIn ); break;
// New2
case 601: Boomerang( bPhaseIn ); break;
case 602: Flash( bPhaseIn ); break;
case 603: Flight( bPhaseIn ); break;
case 604: Jump( bPhaseIn ); break;
case 605: Compress( bPhaseIn ); break;
case 606: Motion( bPhaseIn ); break;
case 607: Manifestation( bPhaseIn ); break;
case 608: Shot( bPhaseIn ); break;
case 609: Reduction( bPhaseIn ); break;
case 610: VHRotation( bPhaseIn ); break;
case 611: Rotate3D( bPhaseIn ); break;
case 612: Spiral( bPhaseIn ); break;
case 613: Flag( bPhaseIn ); break;
case 614: Perpendicular( bPhaseIn ); break;
case 615: Clock( bPhaseIn ); break;
// New3
case 801: Galaxy( bPhaseIn ); break;
case 802: WaveRotate3D( bPhaseIn ); break;
case 803: RandomJump( bPhaseIn ); break;
case 804: Galaxy2( bPhaseIn ); break;
case 805: Roll( bPhaseIn ); break;
case 806: Conga( bPhaseIn ); break;
case 807: _Matrix( bPhaseIn ); break;
case 808: HotPinkSpin( bPhaseIn ); break;
case 809: HopInJumpOut( bPhaseIn ); break;
case 810: ConJoin( bPhaseIn ); break;
case 811: HopsCotch( bPhaseIn ); break;
case 812: Twist( bPhaseIn ); break;
case 813: StarWars( bPhaseIn ); break;
case 814: Squeeze( bPhaseIn ); break;
case 815: Terminator( bPhaseIn ); break;
}
}
}
void SetAnimationAlphaBlendSimple( BOOL bPhaseIn )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
}
void SetAnimationAlphaBlendLetterAZ( BOOL bPhaseIn )
{
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
oManager.AddTransparency( 0, 1, FALSE );
oManager.SetTimeParams( bPhaseIn ? nLetter : letters.count - 1 - nLetter, letters.count, 1 );
}
}
void SetAnimationAlphaBlendLetterRandom( BOOL bPhaseIn, BOOL bRandom, BOOL bScale )
{
double dStartScale = bScale ? 0 : 1;
CRefLetters letters( m_pText->m_arrLetters );
Text::Utils::CPermutator oPermutator( letters.count, bRandom );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
oManager.AddTransparency( 0, 1 );
oManager.AddScale( dStartScale, 1 );
oManager.SetTimeParams( bPhaseIn ? oPermutator[nLetter] : letters.count - 1 - oPermutator[nLetter], letters.count, 3 );
}
}
void SetAnimationAlphaBlendLetterRandomGlass( BOOL bPhaseIn, BOOL bRandom )
{
Text::Transforms::CScaleTransforms::TData arrScales[3];
arrScales[0].data.transform.SetParams( 0, 0 );
arrScales[1].data.transform.SetParams( 2, 2 );
arrScales[2].data.transform.SetParams( 1, 1 );
arrScales[1].duration = 2;
arrScales[2].duration = 1;
CRefLetters letters( m_pText->m_arrLetters );
Text::Utils::CPermutator oPermutator( letters.count, bRandom );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
oManager.AddFadeTransparency( 0, 1, 3, 2 );
oManager.AddScaleTransforms( arrScales, 3 );
oManager.SetTimeParams( bPhaseIn ? oPermutator[nLetter] : letters.count - 1 - oPermutator[nLetter], letters.count, 3 );
}
}
void SetAnimationMove( BOOL bPhaseIn, BOOL bFade, int nHorMove, int nVerMove )
{
if ( nHorMove < 0 ) nHorMove = Utils::c_nLeftBound;
else if( nHorMove > 0 ) nHorMove = Utils::c_nRightBound;
else nHorMove = Utils::c_nEmptyBound;
if ( nVerMove < 0 ) nVerMove = Utils::c_nTopBound;
else if( nVerMove > 0 ) nVerMove = Utils::c_nBottomBound;
else nVerMove = Utils::c_nEmptyBound;
float fX = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, nHorMove );
float fY = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, nVerMove );
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTranslate( fX, fY, 0, 0 );
oTextManager.AddTransparency( 0, 1, bFade );
}
void SetAnimationDropRotate( BOOL bPhaseIn, BOOL bClockText, BOOL bRotateLetters )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
oTextManager.AddRotate( bClockText ? -720 : 720, 0 );
if( bRotateLetters )
{
for( CRefLetters letters( m_pText->m_arrLetters ); letters.count > 0; --letters.count, ++letters.ptr )
{
Text::Transforms::CTransformManager& oLetterManager = letters.ptr->GetTransformManager( bPhaseIn );
oLetterManager.AddRotate( bClockText ? -500 : 500, 0 );
oLetterManager.AddTranslate( letters.ptr->m_oOrigin.X, 0, 0, 0 );
}
}
}
void SetAnimationScaleFrom( BOOL bPhaseIn, BOOL bSmall, int nDropDir = 0 )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
oTextManager.AddScale( bSmall ? 0 : 2, 1 );
if( bSmall && nDropDir != 0 )
{
if ( nDropDir < 0 ) nDropDir = Utils::c_nTopBound;
else if( nDropDir > 0 ) nDropDir = Utils::c_nBottomBound;
float fY = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, nDropDir );
oTextManager.AddTranslate( 0, fY, 0, 0 );
}
}
void SetAnimationScaleFromXY( BOOL bPhaseIn, BOOL bRevers )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
double dx = 0;
double dy = 0;
if( bPhaseIn )
{
if( bRevers )
dy = 2;
else
dx = 2;
}
else
{
if( bRevers )
dx = 2;
else
dy = 2;
}
oTextManager.AddScale( dx, dy, 1, 1 );
}
void SetAnimationRotate( BOOL bPhaseIn, BOOL bClockText, int nScaleDir = 0 )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
double angle = 0;
if( bPhaseIn )
angle = bClockText ? -1440 : 1440;
else
angle = bClockText ? 1440 : -1440;
oTextManager.AddRotate( angle, 0 );
if( nScaleDir != 0 )
{
double scale = 0;
if( bPhaseIn )
scale = nScaleDir < 0 ? 2 : 0;
else
scale = nScaleDir < 0 ? 0 : 2;
oTextManager.AddScale( scale, 1 );
}
}
void SetAnimationStretchScale( BOOL bPhaseIn, int nHorScaleDir, int nVerScaleDir )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
if( bPhaseIn )
{
double dScaleX = 1;
double dScaleY = 1;
if( nHorScaleDir != 0 )
dScaleX = nHorScaleDir < 0 ? 1.5 : 0;
if( nVerScaleDir != 0 )
dScaleY = nVerScaleDir < 0 ? 2 : 0;
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oLetterManager = letters[nLetter].GetTransformManager( bPhaseIn );
oLetterManager.AddScale( dScaleX, dScaleY, 1, 1 );
}
}
else
{
double dScaleX = 1;
double dScaleY = 1;
if( nHorScaleDir != 0 )
dScaleX = nHorScaleDir < 0 ? 0 : 1.5;
if( nVerScaleDir != 0 )
dScaleY = nVerScaleDir < 0 ? 0 : 1.5;
oTextManager.AddScale( dScaleX, dScaleY, 1, 1 );
}
}
void SetAnimationStretchScaleMove( BOOL bPhaseIn, BOOL bStretch )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
double dMoveFactor = 0;
if( bPhaseIn )
dMoveFactor = bStretch ? -0.5 : 0.5;
else
dMoveFactor = bStretch ? 0.75 : -0.75;
double dScaleX = bPhaseIn ? 0 : 1;
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oLetterManager = letters[nLetter].GetTransformManager( bPhaseIn );
oLetterManager.AddScale( dScaleX, 1, 1, 1 );
double dx = letters[nLetter].m_oOrigin.X * dMoveFactor;
oLetterManager.AddTranslate( dx, 0, 0, 0 );
}
}
void SetAnimationStretchScaleMove2( BOOL bPhaseIn, BOOL bStretch )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
double dMoveFactor = 0;
if( bPhaseIn )
dMoveFactor = bStretch ? -0.5 : 0.5;
else
dMoveFactor = bStretch ? 0.75 : -0.75;
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oLetterManager = letters[nLetter].GetTransformManager( bPhaseIn );
oLetterManager.AddScale( 0, 0, 1, 1 );
double dx = letters[nLetter].m_oOrigin.X * dMoveFactor;
double dy = letters[nLetter].m_oOrigin.Y * dMoveFactor;
oLetterManager.AddTranslate( dx, dy, 0, 0 );
}
}
void SetAnimationStretchScaleMove3( BOOL bPhaseIn, int nHorScaleDir, int nVerScaleDir, BOOL bStretch )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
double dMoveFactor = 0;
if( bPhaseIn )
dMoveFactor = bStretch ? -0.5 : 0.5;
else
dMoveFactor = bStretch ? 0.75 : -0.75;
double dScaleX = 1;
if( nHorScaleDir != 0 )
dScaleX = nHorScaleDir < 0 ? 0 : 1.5;
double dScaleY = 1;
if( nVerScaleDir != 0 )
dScaleY = nVerScaleDir < 0 ? 0 : 1.5;
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oLetterManager = letters[nLetter].GetTransformManager( bPhaseIn );
oLetterManager.AddScale( dScaleX, dScaleY, 1, 1 );
double dx = letters[nLetter].m_oOrigin.X * dMoveFactor;
double dy = letters[nLetter].m_oOrigin.Y * (nVerScaleDir > 0 ? 1 : 0);
oLetterManager.AddTranslate( dx, dy, 0, 0 );
}
}
// Appear Displace
void RandomMovements( BOOL bPhaseIn )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
float scale = Random( 0.0f, 2.0f );
oManager.AddScale( scale, 1 );
float dx = m_pText->m_oPathBoundRect.Width * Random( -0.5f, 0.5f );
float dy = m_pText->m_oPathBoundRect.Height * Random( -0.5f, 0.5f );
oManager.AddTranslate( dx, dy, 0, 0 );
float angle = Random( -1440.0f, 1440.0f );
oManager.AddRotate( angle, 0 );
}
}
void AppearFade( BOOL bPhaseIn )
{
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
oManager.SetTimeParams( nLetter, letters.count, 1 );
oManager.AddTransparency( 0, 1 );
}
}
void AppearShade( BOOL bPhaseIn )
{
// сдвиг
Text::Transforms::CShearTransforms::TData arrShears[3];
arrShears[0].data.transform.SetParams( 0, 0 );
arrShears[1].data.transform.SetParams( -1.5, 0 );
arrShears[2].data.transform.SetParams( 0, 0 );
// движение
float fX = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nLeftBound );
Text::Transforms::CTranslateTransforms::TData arrMoves[3];
arrMoves[0].data.transform.SetParams( fX, 0 );
arrMoves[1].data.transform.SetParams( 0, 0 );
arrMoves[2].data.transform.SetParams( 0, 0 );
// применить трансформы
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddShearTransforms( arrShears, 3 );
oTextManager.AddTranslateTransforms( arrMoves, 3 );
oTextManager.AddTransparency( 0, 1, FALSE );
// теперь буквы
Text::Transforms::CScaleTransforms::TData arrScales[3];
arrScales[0].data.transform.SetParams( 1, 1 );
arrScales[1].data.transform.SetParams( 1, 1 );
arrScales[2].data.transform.SetParams( 1, 1 );
float fTextRightBound = m_pText->m_oPathBoundRect.GetRight();
arrMoves[0].data.transform.SetParams( 0, 0 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
CLetterEntity* pLetter = letters.ptr + nLetter;
float fLetterRightBound = pLetter->m_oPathBoundRect.GetRight();
if( pLetter->m_bNotLetter )
{
arrMoves [1].data.transform.SetParams( pLetter->m_oPathBoundRect.Width * 0.1, 0 );
arrScales[1].data.transform.SetParams( 0.8, 1 );
}
else
{
arrMoves [1].data.transform.SetParams( (fTextRightBound - fLetterRightBound) * 0.2, 0 );
arrScales[1].data.transform.SetParams( 0.7, 1 );
}
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
oManager.AddScaleTransforms( arrScales, 3 );
oManager.AddTranslateTransforms( arrMoves, 3 );
}
}
void AppearRotate( BOOL bPhaseIn )
{
Text::Transforms::CScaleTransforms::TData arrScales[3];
arrScales[0].data.transform.SetParams( 0, 0 );
arrScales[1].data.transform.SetParams( 1.5, 1.5 );
arrScales[2].data.transform.SetParams( 1, 1 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
oManager.AddRotate( 0, 360*3 );
oManager.AddScaleTransforms( arrScales, 3 );
}
}
void AppearRandom( BOOL bPhaseIn )
{
Text::Transforms::CScaleTransforms::TData arrScales[3];
Text::Transforms::CTranslateTransforms::TData arrMoves[3];
arrScales[0].data.transform.SetParams( 0, 0);
arrScales[1].data.transform.SetParams( 1.5, 1.5 );
arrScales[2].data.transform.SetParams( 1, 1 );
float dx = m_pText->m_oPathBoundRect.Width * 0.1f;
arrMoves[0].data.transform.SetParams( 0, 0);
arrMoves[1].data.transform.SetParams( dx, 0 );
arrMoves[2].data.transform.SetParams( 0, 0 );
CRefLetters letters( m_pText->m_arrLetters );
Text::Utils::CPermutator oPermutator( letters.count, TRUE );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
oManager.AddFadeTransparency( 0, 1 );
oManager.AddScaleTransforms( arrScales, 3 );
oManager.AddTranslateTransforms( arrMoves, 3 );
oManager.SetTimeParams( nLetter, letters.count, 1 );
}
}
void Airport( BOOL bPhaseIn )
{
}
void AppearShake( BOOL bPhaseIn )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1, FALSE );
float fY = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nTopBound );
const int c_nDropPaths = 6;
const int c_nRandomPaths = 5;
Text::Transforms::CTransparencyTransforms::TData arrAlphas[3 + c_nRandomPaths];
arrAlphas[0].data.transform.SetParams( 0 );
for( int i = 1; i < 3 + c_nRandomPaths; i++ )
{
arrAlphas[i].data.transform.SetParams( 1 );
arrAlphas[i].data.interpolation = FALSE;
}
Text::Transforms::CRotateTransforms::TData arrAngles[3 + c_nRandomPaths];
Text::Transforms::CTranslateTransforms::TData arrMoves[3 + c_nRandomPaths];
arrAngles[0].data.transform.SetParams( 0 );
arrAngles[1].data.transform.SetParams( 0 );
arrAngles[2 + c_nRandomPaths].data.transform.SetParams( 0 );
arrMoves[0].data.transform.SetParams( 0, fY );
arrMoves[1].data.transform.SetParams( 0, 0 );
arrMoves[2 + c_nRandomPaths].data.transform.SetParams( 0, 0 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
arrAlphas[1].duration = arrMoves[1].duration = arrAngles[1].duration = c_nDropPaths + 1;
Gdiplus::PointF factor(
m_fLineSpacing * 0.1f,
m_fLineSpacing * 0.2f
);
float angle = (!letters[nLetter].m_bNotLetter) ? 20 : float(::atan2( m_fLineSpacing, letters[nLetter].m_oPathBoundRect.Width * 2 ) / IPP_PI180);
for( int i = 2; i < 2 + c_nRandomPaths; i++ )
{
arrMoves [i].data.transform.SetParams( Random(-1.0f, 1.0f) * factor.X, Random(-1.0f, 1.0f) * factor.Y );
arrAngles[i].data.transform.SetParams( Random(0.3f, 1.0f) * angle * ((i % 2) * 2 - 1) );
}
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
oManager.AddRotateTransforms( arrAngles, 3 + c_nRandomPaths );
oManager.AddTranslateTransforms( arrMoves, 3 + c_nRandomPaths );
oManager.AddTransparencyTransforms( arrAlphas, 3 + c_nRandomPaths );
oManager.SetTimeParams( nLetter, letters.count, 5 );
}
}
void AppearWedge( BOOL bPhaseIn )
{
const int nRandomPaths = 4;
int nCountRepeats = 0;
int arrRepeats[1 + nRandomPaths];
int i = 0;
for( i = 0; i <= nRandomPaths; i++ )
{
arrRepeats[i] = ::rand() % 3 + 5;
nCountRepeats += arrRepeats[i];
}
Text::Transforms::CTransparencyTransforms::TData arrAlphas[2 + nRandomPaths];
arrAlphas[0].data.transform.SetParams( 0 );
for( i = 1; i < nRandomPaths + 2; i++ )
{
arrAlphas[i].data.transform.SetParams( 1 );
arrAlphas[i].duration = nCountRepeats / nRandomPaths + 1;
}
Utils::CPermutator oPermutator( nRandomPaths + 1, TRUE );
Text::Transforms::CScaleTransforms::TData arrScales[2 + nRandomPaths];
arrScales[0].data.transform.SetParams( 0, 0 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
oManager.AddTransparencyTransforms( arrAlphas, nRandomPaths + 2 );
float dx = m_fLineSpacing * 0.2f;
float dy = m_fLineSpacing * 0.5f;
dy *= float((/*::rand()*/ nLetter % 2) * 2 - 1);
oManager.AddTranslate( dx, dy, 0, 0 );
oPermutator.Refresh();
for( i = 1; i <= nRandomPaths; i++ )
{
float scale = Random( 0.3f, 1.5f );
arrScales[i].data.transform.SetParams( scale, scale );
arrScales[i].duration = oPermutator[i - 1] + 1;
}
arrScales[i].data.transform.SetParams( 1, 1 );
arrScales[i].duration = oPermutator[i - 1] + 1;
oManager.AddScaleTransforms( arrScales, nRandomPaths + 2 );
}
}
void AppearStream( BOOL bPhaseIn )
{
}
// Appear Waves
void WaveSimple( BOOL bPhaseIn )
{
float fX = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nLeftBound );
const int c_nPaths = 25;
Text::Transforms::CTranslateTransforms::TData arrMoves[c_nPaths + 4];
Text::Transforms::CScaleTransforms::TData arrScales[5];
arrScales[2].data.transform.SetParams( 2, 2 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
double phase = IPP_2PI * (Utils::GetHorCenter(pLetter->m_oPathBoundRect) - m_pText->m_oPathBoundRect.X) / m_pText->m_oPathBoundRect.Width;
for( int i = 0; i < c_nPaths; i++ )
{
double dy = ::sin(IPP_2PI * i / (c_nPaths - 1) + phase) * m_fLineSpacing;
arrMoves[i].data.transform.SetParams( 0, dy );
}
arrMoves[c_nPaths + 0].data.transform.dY = arrMoves[c_nPaths - 1].data.transform.dY;
arrMoves[c_nPaths + 0].duration = letters.count - nLetter;
arrMoves[c_nPaths + 1].data.transform.SetParams( m_fLineSpacing * 0.5, m_fLineSpacing * 0.5 );
arrMoves[c_nPaths + 1].duration = 3;
arrMoves[c_nPaths + 2].data.transform.SetParams( 0, 0 );
arrMoves[c_nPaths + 2].duration = 3;
arrMoves[c_nPaths + 3].data.transform.SetParams( 0, 0 );
arrMoves[c_nPaths + 3].duration = nLetter;
arrScales[1].duration = c_nPaths + letters.count - nLetter;
arrScales[2].duration = 3;
arrScales[3].duration = 3;
arrScales[4].duration = nLetter + 1;
if( !pLetter->m_bNotLetter )
{
oManager.AddScaleTransforms( arrScales, 5 );
}
oManager.AddTranslateTransforms( arrMoves, c_nPaths + 4 );
}
double nRepeats = 0;
for( int i = 1; i < c_nPaths + 4; i++ )
{
nRepeats += arrMoves[i].duration;
}
Text::Transforms::CTranslateTransforms::TData arrTextMoves[3];
arrTextMoves[0].data.transform.SetParams( fX, 0 );
arrTextMoves[1].data.transform.SetParams( 0, 0 );
arrTextMoves[1].duration = c_nPaths;
arrTextMoves[2].data.transform.SetParams( 0, 0 );
arrTextMoves[2].duration = nRepeats - c_nPaths + 1;
// применить трансформы
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTranslateTransforms( arrTextMoves, 3 );
oTextManager.AddTransparency( 0, 1, FALSE );
}
void WaveZoom( BOOL bPhaseIn )
{
Text::Transforms::CScaleTransforms::TData arrScales[3];
arrScales[0].data.transform.SetParams( 1, 1 );
arrScales[1].data.transform.SetParams( 2.5, 2.5 );
arrScales[2].data.transform.SetParams( 1, 1 );
Text::Transforms::CTranslateTransforms::TData arrMoves[3];
arrMoves[0].data.transform.SetParams( 0, 0 );
arrMoves[1].data.transform.SetParams( m_fLineSpacing * 0.5, 0 );
arrMoves[2].data.transform.SetParams( 0, 0 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
oManager.AddScaleTransforms( arrScales, 3 );
oManager.AddTranslateTransforms( arrMoves, 3 );
oManager.AddFadeTransparency( 0, 1 );
oManager.SetTimeParams( nLetter, letters.count, 3 );
}
}
void WaveFall( BOOL bPhaseIn )
{
float fX = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nLeftBound );
const int c_nPaths = 25;
Text::Transforms::CTranslateTransforms::TData arrMoves[c_nPaths + 4];
Text::Transforms::CScaleTransforms::TData arrScales[5];
Text::Transforms::CRotateTransforms::TData arrAngles[5];
arrScales[2].data.transform.SetParams( 2, 2 );
arrAngles[2].data.transform.SetParams( 360 );
arrAngles[3].data.transform.SetParams( 720 );
arrAngles[4].data.transform.SetParams( 720 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
double phase = IPP_2PI * (Utils::GetHorCenter(pLetter->m_oPathBoundRect) - m_pText->m_oPathBoundRect.X) / m_pText->m_oPathBoundRect.Width;
for( int i = 0; i < c_nPaths; i++ )
{
double dy = ::sin(IPP_2PI * i / (c_nPaths - 1) + phase) * m_fLineSpacing;
arrMoves[i].data.transform.SetParams( 0, dy );
}
arrMoves[c_nPaths + 0].data.transform.dY = arrMoves[c_nPaths - 1].data.transform.dY;
arrMoves[c_nPaths + 0].duration = letters.count - nLetter;
arrMoves[c_nPaths + 1].data.transform.SetParams( m_fLineSpacing * 0.5, m_fLineSpacing * 0.5 );
arrMoves[c_nPaths + 1].duration = 3;
arrMoves[c_nPaths + 2].data.transform.SetParams( 0, 0 );
arrMoves[c_nPaths + 2].duration = 3;
arrMoves[c_nPaths + 3].data.transform.SetParams( 0, 0 );
arrMoves[c_nPaths + 3].duration = nLetter;
arrAngles[1].duration = arrScales[1].duration = c_nPaths + letters.count - nLetter;
arrAngles[2].duration = arrScales[2].duration = 3;
arrAngles[3].duration = arrScales[3].duration = 3;
arrAngles[4].duration = arrScales[4].duration = nLetter + 1;
if( !pLetter->m_bNotLetter )
{
oManager.AddRotateTransforms( arrAngles, 5 );
oManager.AddScaleTransforms( arrScales, 5 );
}
oManager.AddTranslateTransforms( arrMoves, c_nPaths + 4 );
}
double nRepeats = 0;
for( int i = 1; i < c_nPaths + 4; i++ )
{
nRepeats += arrMoves[i].duration;
}
Text::Transforms::CTranslateTransforms::TData arrTextMoves[3];
arrTextMoves[0].data.transform.SetParams( fX, 0 );
arrTextMoves[1].data.transform.SetParams( 0, 0 );
arrTextMoves[1].duration = c_nPaths;
arrTextMoves[2].data.transform.SetParams( 0, 0 );
arrTextMoves[2].duration = nRepeats - c_nPaths + 1;
// применить трансформы
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTranslateTransforms( arrTextMoves, 3 );
oTextManager.AddTransparency( 0, 1, FALSE );
}
void WaveRunShift( BOOL bPhaseIn )
{
float fX = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nLeftBound );
const int c_nPaths = 25;
Text::Transforms::CTranslateTransforms::TData arrMoves[c_nPaths + 3];
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
double phase = IPP_2PI * (Utils::GetHorCenter(pLetter->m_oPathBoundRect) - m_pText->m_oPathBoundRect.X) / m_pText->m_oPathBoundRect.Width;
for( int i = 0; i < c_nPaths; i++ )
{
double dy = ::sin(IPP_2PI * i / (c_nPaths - 1) + phase) * m_fLineSpacing;
arrMoves[i].data.transform.SetParams( 0, dy );
}
arrMoves[c_nPaths + 0].data.transform.dY = arrMoves[c_nPaths - 1].data.transform.dY;
arrMoves[c_nPaths + 0].duration = letters.count - nLetter;
arrMoves[c_nPaths + 1].data.transform.SetParams( 0, 0 );
arrMoves[c_nPaths + 1].duration = 3;
arrMoves[c_nPaths + 2].data.transform.SetParams( 0, 0 );
arrMoves[c_nPaths + 2].duration = nLetter;
oManager.AddTranslateTransforms( arrMoves, c_nPaths + 3 );
}
double nRepeats = 0;
for( int i = 1; i < c_nPaths + 3; i++ )
{
nRepeats += arrMoves[i].duration;
}
Text::Transforms::CTranslateTransforms::TData arrTextMoves[3];
arrTextMoves[0].data.transform.SetParams( fX, 0 );
arrTextMoves[1].data.transform.SetParams( 0, 0 );
arrTextMoves[1].duration = c_nPaths;
arrTextMoves[2].data.transform.SetParams( 0, 0 );
arrTextMoves[2].duration = nRepeats - c_nPaths;
// применить трансформы
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTranslateTransforms( arrTextMoves, 3 );
oTextManager.AddTransparency( 0, 1, FALSE );
}
void WaveSwing( BOOL bPhaseIn )
{
float fY = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nTopBound );
const int c_nPoints = 8;
Text::Transforms::CTransparencyTransforms::TData arrAlphas[c_nPoints];
arrAlphas[1].data.transform.SetParams( 0 );
for( int i = 1; i < c_nPoints; i++ )
{
arrAlphas[i].data.transform.SetParams( 1 );
arrAlphas[i].data.interpolation = FALSE;
}
Text::Transforms::CTranslateTransforms::TData arrMoves[c_nPoints];
for( int i = 0; i < c_nPoints - 1; i += 2 )
{
arrMoves[i].data.transform.SetParams( 0, fY / (1 << (i/2)) );
arrMoves[i + 1].data.transform.SetParams( 0, m_fLineSpacing * 0.2 / (1 << (i/2)) );
}
arrMoves[c_nPoints - 1].data.transform.SetParams( 0, 0 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
oManager.AddTransparencyTransforms( arrAlphas, c_nPoints );
oManager.AddTranslateTransforms( arrMoves, c_nPoints );
oManager.SetTimeParams( nLetter, letters.count, letters.count );
}
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1, FALSE );
}
void WaveRun( BOOL bPhaseIn )
{
}
void WaveZoomVertical( BOOL bPhaseIn )
{
const int c_nRepeats = 2;
Text::Transforms::CTransparencyTransforms::TData arrAlphas[2 + c_nRepeats];
arrAlphas[0].data.transform.SetParams( 0 );
for( int i = 1; i < c_nRepeats + 2; i++ )
{
arrAlphas[i].data.transform.SetParams( 1 );
arrAlphas[i].data.interpolation = FALSE;
}
Text::Transforms::CScaleTransforms::TData arrScales[2 + c_nRepeats];
arrScales[0].data.transform.SetParams( 1, 0 );
for( int i = 1; i < c_nRepeats + 1; i += 2 )
{
arrScales[i].data.transform.SetParams( 1, 3 );
arrScales[i + 1].data.transform.SetParams( 1, 0.5 );
}
arrScales[c_nRepeats + 1].data.transform.SetParams( 1, 1 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
oManager.AddScaleTransforms( arrScales, c_nRepeats + 2 );
oManager.AddTransparencyTransforms( arrAlphas, c_nRepeats + 2 );
oManager.SetTimeParams( nLetter, letters.count, letters.count );
}
}
void WaveShift( BOOL bPhaseIn )
{
const int c_nPhase1 = 1;
const int c_nPhase2 = 7;
const int c_nPhase3 = 9;
const int c_nPoints = c_nPhase3;
Text::Transforms::CTransparencyTransforms::TData arrAlphas[c_nPoints];
Text::Transforms::CScaleTransforms::TData arrScales[c_nPoints];
Text::Transforms::CTranslateTransforms::TData arrMoves [c_nPoints];
double dTop = m_fLineSpacing * -0.7;
double dBottom = m_fLineSpacing * 1.4;
double dLeft = m_fLineSpacing * 0.25;
double dRight = m_fLineSpacing * 0.75;
int i = 0;
// phase 1
arrAlphas[0].data.transform.SetParams( 0 );
arrScales[0].data.transform.SetParams( 0, 0 );
arrMoves [0].data.transform.SetParams( dRight, dBottom );
// phase 2
for( i = c_nPhase1; i < c_nPhase2; i++ )
{
arrAlphas[i].data.transform.SetParams( 1 );
double x = double(i - c_nPhase1 + 1)/(c_nPhase2 - c_nPhase1);
double scale = x * (2 - x) * 1.4;
arrScales[i].data.transform.SetParams( scale, scale );
double dX = dRight - x * (dRight - dLeft);
double dY = dBottom - x * (2 - x) * (dBottom - dTop);
arrMoves[i].data.transform.SetParams( dX, dY );
}
// phase 3
for( i = c_nPhase2; i < c_nPhase3; i++ )
{
arrAlphas[i].data.transform.SetParams( 1 );
double x = double(i - c_nPhase2 + 1)/(c_nPhase3 - c_nPhase2);
double scale = 1.4 - x * x * (1.4 - 1) ;
arrScales[i].data.transform.SetParams( scale, scale );
double dX = dLeft * (1 - x);
double dY = dTop * (1 - x * x);
arrMoves[i].data.transform.SetParams( dX, dY );
}
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
oManager.AddTransparencyTransforms( arrAlphas, c_nPoints );
oManager.AddScaleTransforms( arrScales, c_nPoints );
oManager.AddTranslateTransforms( arrMoves, c_nPoints );
oManager.SetTimeParams( nLetter, letters.count, 5 );
}
}
void WavePulse( BOOL bPhaseIn )
{
const int c_nRepeats = 6;
Text::Transforms::CTransparencyTransforms::TData arrAlphas[2 + c_nRepeats];
arrAlphas[0].data.transform.SetParams( 0 );
for( int i = 1; i < c_nRepeats + 2; i++ )
{
arrAlphas[i].data.transform.SetParams( 1 );
arrAlphas[i].data.interpolation = FALSE;
}
Text::Transforms::CScaleTransforms::TData arrScales[2 + c_nRepeats];
for( int i = 0; i < c_nRepeats + 1; i += 2 )
{
arrScales[i + 0].data.transform.SetParams( 1, 0 );
arrScales[i + 1].data.transform.SetParams( 1, 3 );
}
arrScales[c_nRepeats + 1].data.transform.SetParams( 1, 1 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
oManager.AddScaleTransforms( arrScales, c_nRepeats + 2 );
oManager.AddTransparencyTransforms( arrAlphas, c_nRepeats + 2 );
oManager.SetTimeParams( nLetter, letters.count, letters.count * 3 );
}
}
// New
void Ejection( BOOL bPhaseIn )
{
Text::Transforms::CTranslateTransforms::TData arrMoves[3];
float fY = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nBottomBound );
arrMoves[0].data.transform.SetParams( 0, fY );
arrMoves[1].data.transform.SetParams( 0, -m_fLineSpacing * 0.75 );
arrMoves[2].data.transform.SetParams( 0, 0 );
arrMoves[1].duration = fY * 100;
arrMoves[2].duration = m_fLineSpacing * 100;
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTranslateTransforms( arrMoves, 3 );
oTextManager.AddTransparency( 0, 1 );
}
void Ellipse( BOOL bPhaseIn )
{
const int c_nPoints = 5;
Text::Transforms::CTransparencyTransforms::TData arrAlphas[c_nPoints];
Text::Transforms::CScaleTransforms::TData arrScales[c_nPoints];
Text::Transforms::CRotateAtTransforms::TData arrAngles[c_nPoints];
arrAlphas[0].data.transform.SetParams( 0 );
arrScales[0].data.transform.SetParams( 0, 0 );
arrAngles[0].data.transform.SetParams( 0, 0, m_fLineSpacing );
for( int i = 1; i < c_nPoints; i++ )
{
arrAlphas[i].data.transform.SetParams( 1 );
arrScales[i].data.transform.SetParams( 1, 1 );
arrAngles[i].data.transform.SetParams( i * 90, 0, m_fLineSpacing );
}
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
oManager.AddTransparencyTransforms( arrAlphas, c_nPoints );
oManager.AddScaleTransforms( arrScales, c_nPoints );
oManager.AddRotateAtTransforms( arrAngles, c_nPoints );
oManager.SetTimeParams( nLetter, letters.count, letters.count );
}
}
void Wheel( BOOL bPhaseIn )
{
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
oManager.AddTransparency( 0, 1 );
oManager.AddScale( 0, 1 );
oManager.AddRotate( 0, 720 );
oManager.SetTimeParams( nLetter, letters.count, 4 );
}
}
void Miscarry( BOOL bPhaseIn )
{
Text::Transforms::CTranslateTransforms::TData arrMoves[3];
Text::Transforms::CRotateTransforms::TData arrAngles[3];
Text::Transforms::CScaleTransforms::TData arrScales[3]; // для линий перечёркивания
arrAngles[1].data.transform.SetParams( 90 );
arrScales[0].data.transform.SetParams( 1, 1 );
arrScales[1].data.transform.SetParams( 1, 1 );
arrScales[2].data.transform.SetParams( 1, 1 );
CRefLetters letters( m_pText->m_arrLetters );
CRefLines lines( m_pText->m_arrLines );
for( int nLine = 0; nLine < lines.count; nLine++ )
{
CTextEntity::CTextLine* pLine = lines.ptr + nLine;
CLetterEntity* pLetter = letters.ptr + pLine->m_nFirstLetter;
float fLeft = Utils::GetOffsetRect( m_oLayoutRect, pLetter->m_oPathBoundRect, Utils::c_nLeftBound );
float fRight = Utils::GetOffsetRect( m_pText->m_oPathBoundRect, pLetter->m_oPathBoundRect, Utils::c_nRightBound ) - pLetter->m_oPathBoundRect.Width;
arrMoves[0].data.transform.SetParams( fLeft, 0 );
arrMoves[1].data.transform.SetParams( fRight, 0 );
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
if( pLetter->m_bNotLetter )
{
float fScale = m_fLineSpacing * 0.5f / pLetter->m_oPathBoundRect.Width;
arrScales[1].data.transform.SetParams( fScale, 1 );
oManager.AddScaleTransforms( arrScales, 3 );
arrMoves[1].data.transform.dX += pLetter->m_oPathBoundRect.Width * 0.5f - pLetter->m_oPathBoundRect.Height;
}
oManager.AddRotateTransforms( arrAngles, 3 );
oManager.AddTranslateTransforms( arrMoves, 3 );
oManager.AddTransparency( 0, 1, FALSE );
for( int nLetter = 1; nLetter < pLine->m_nLength; nLetter++ )
{
++pLetter;
fRight = Utils::GetOffsetRect( m_pText->m_oPathBoundRect, pLetter->m_oPathBoundRect, Utils::c_nRightBound ) - pLetter->m_oPathBoundRect.Width;
Text::Transforms::CTransformManager& oLocalManager = pLetter->GetTransformManager( bPhaseIn );
if( pLetter->m_bNotLetter )
{
float fScale = m_fLineSpacing * 0.5f / pLetter->m_oPathBoundRect.Width;
oLocalManager.AddScale( fScale, 1, 1, 1 );
fRight += pLetter->m_oPathBoundRect.Width * 0.5f - pLetter->m_oPathBoundRect.Height;
}
oLocalManager.AddRotate( 90, 0 );
oLocalManager.AddTranslate( fRight, 0, 0, 0 );
oLocalManager.AddTransparency( 0, 1 );
oLocalManager.SetTimeParams( 0.5, 0.5 );
}
}
}
void Rotation( BOOL bPhaseIn )
{
Text::Transforms::CScaleTransforms::TData arrScales[3];
arrScales[0].data.transform.SetParams( 1, 1 );
arrScales[1].data.transform.SetParams( -1, 1 );
arrScales[2].data.transform.SetParams( 1, 1 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
if( !pLetter->m_bNotLetter )
{
oManager.AddScaleTransforms( arrScales, 3 );
}
oManager.AddTransparency( 0, 1 );
oManager.SetTimeParams( nLetter, letters.count, 4 );
}
}
void Increase( BOOL bPhaseIn )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
Text::Transforms::CScaleTransforms::TData arrScales[3];
Text::Transforms::CTranslateTransforms::TData arrMoves[3];
arrScales[0].data.transform.SetParams( 0, 0 );
arrScales[1].data.transform.SetParams( 3, 3 );
arrScales[2].data.transform.SetParams( 1, 1 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
float scale = !pLetter->m_bNotLetter ? 3 : (2 * m_fLineSpacing / pLetter->m_oPathBoundRect.Width);
arrScales[1].data.transform.SetParams( scale, 3 );
float fx = Utils::GetHorOffsetCenters( pLetter->m_oPathBoundRect, m_pText->m_oPathBoundRect );
float fy = Utils::GetVerOffsetCenters( pLetter->m_oPathBoundRect, m_pText->m_oPathBoundRect );
arrMoves[0].data.transform.SetParams( fx, fy );
arrMoves[1].data.transform.SetParams( fx, fy );
oManager.AddScaleTransforms( arrScales, 3 );
oManager.AddTranslateTransforms( arrMoves, 3 );
}
}
void TwoString( BOOL bPhaseIn )
{
}
void Tumbling( BOOL bPhaseIn )
{
Text::Transforms::CScaleTransforms::TData arrScales[3];
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
float fy = Utils::GetOffsetRect( m_oLayoutRect, pLetter->m_oPathBoundRect, Utils::c_nTopBound );
float fx = m_fLineSpacing / 3;
arrScales[0].data.transform.dScaleX = !pLetter->m_bNotLetter ? 1 : 0;
arrScales[1].data.transform.dScaleX = !pLetter->m_bNotLetter ? -1 : 0.5;
oManager.AddScaleTransforms( arrScales, 3 );
oManager.AddRotate( 360, 0 );
oManager.AddTranslate( fx, fy, 0, 0 );
oManager.AddTransparency( 0, 1 );
oManager.SetTimeParams( nLetter, letters.count, 5 );
}
}
void Leave( BOOL bPhaseIn )
{
Text::Transforms::CScaleTransforms::TData arrScales[3];
arrScales[0].data.transform.SetParams( 0, 0 );
arrScales[1].data.transform.SetParams( 1, 1 );
arrScales[2].data.transform.SetParams( 1, 1 );
arrScales[2].data.interpolation = FALSE;
arrScales[2].duration = 4;
CRefLines lines( m_pText->m_arrLines );
for( ; lines.count > 0; --lines.count, ++lines.ptr )
{
float offset = Utils::GetOffsetRect( m_pText->m_oPathBoundRect, lines.ptr->m_oPathBoundRect, Utils::c_nLeftBound );
CRefLetters letters( m_pText->m_arrLetters, lines.ptr->m_nFirstLetter, lines.ptr->m_nLength );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
float fx = Utils::GetOffsetRect( m_pText->m_oPathBoundRect, pLetter->m_oPathBoundRect, Utils::c_nLeftBound );
double dTimeOffset = abs((offset - fx) / offset);
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
if( pLetter->m_bNotLetter )
{
oManager.AddScale( 0, 1, 1, 1 );
fx += pLetter->m_oPathBoundRect.Width / 2;
}
else
{
oManager.AddScaleTransforms( arrScales, 3 );
}
oManager.AddTranslate( fx, 0, 0, 0 );
oManager.AddFadeTransparency( 0, 1, 1, 6 );
oManager.SetTimeParams( dTimeOffset, 1 - dTimeOffset );
}
}
}
void Unfold( BOOL bPhaseIn )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1, FALSE );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
float fx = Utils::GetOffsetRect( m_oLayoutRect, pLetter->m_oPathBoundRect, Utils::c_nLeftBound );
float fy = Utils::GetOffsetRect( m_oLayoutRect, pLetter->m_oPathBoundRect, Utils::c_nTopBound );
if( pLetter->m_bNotLetter )
{
oManager.AddScale( 0, 1, 1, 1 );
fx += pLetter->m_oPathBoundRect.Width / 2;
}
oManager.AddTranslate( fx, fy, 0, 0 );
oManager.SetTimeParams( 0, (double(nLetter + 1) / letters.count + 1) / 2 );
}
}
void Centrifuge( BOOL bPhaseIn )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
oTextManager.AddScale( 0, 1 );
oTextManager.AddRotate( -720, 0 );
}
void HorizontalRotation( BOOL bPhaseIn )
{
Text::Transforms::CScaleTransforms::TData arrScales[6];
arrScales[0].data.transform.SetParams( 0, 1 );
arrScales[1].data.transform.SetParams( 1, 1 );
arrScales[2].data.transform.SetParams( 0, 1 );
arrScales[3].data.transform.SetParams( -1, 1 );
arrScales[4].data.transform.SetParams( 0, 1 );
arrScales[5].data.transform.SetParams( 1, 1 );
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddScaleTransforms( arrScales, 6 );
oTextManager.AddFadeTransparency( 0, 1, 1, 6 );
}
void HorizontalRotation3D( BOOL bPhaseIn )
{
HorizontalRotation( bPhaseIn );
Text::Transforms::CScaleTransforms::TData arrScales[6];
CRefLines lines( m_pText->m_arrLines );
for( ; lines.count > 0; --lines.count, ++lines.ptr )
{
CRefLetters letters( m_pText->m_arrLetters, lines.ptr->m_nFirstLetter, lines.ptr->m_nLength );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
if( pLetter->m_bNotLetter )
continue;
double dScaleY = (pLetter->m_oPathBoundRect.X - m_pText->m_oPathBoundRect.X) / m_pText->m_oPathBoundRect.Width;
arrScales[0].data.transform.SetParams( dScaleY, IPP_PI * (1 - dScaleY) );
arrScales[2].data.transform.SetParams( 1 , IPP_PI * dScaleY );
arrScales[4].data.transform.SetParams( dScaleY, IPP_PI * (1 - dScaleY) );
oManager.AddScaleTransforms( arrScales, 6 );
}
}
}
void VerticalRotation( BOOL bPhaseIn )
{
Text::Transforms::CScaleTransforms::TData arrScales[6];
arrScales[0].data.transform.SetParams( 1, 0 );
arrScales[1].data.transform.SetParams( 1, 1 );
arrScales[2].data.transform.SetParams( 1, 0 );
arrScales[3].data.transform.SetParams( 1, -1 );
arrScales[4].data.transform.SetParams( 1, 0 );
arrScales[5].data.transform.SetParams( 1, 1 );
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddScaleTransforms( arrScales, 6 );
oTextManager.AddFadeTransparency( 0, 1, 1, 6 );
}
void CheChe( BOOL bPhaseIn )
{
const int c_nCycles = 5;
const int c_nPoints = c_nCycles * 2;
Text::Transforms::CScaleTransforms::TData arrScales[c_nPoints];
Text::Transforms::CTransparencyTransforms::TData arrAlphas[c_nPoints];
Text::Transforms::CRotateTransforms::TData arrAngles[c_nPoints];
Text::Transforms::CTranslateTransforms::TData arrMoves [c_nPoints];
for( int i = 0; i < c_nPoints; i += 2 )
{
arrScales[i].data.transform.SetParams( 0, 0 );
arrAlphas[i].data.transform.SetParams( double(i/2) / c_nPoints );
arrAngles[i].data.transform.SetParams( 60 );
arrMoves [i].data.transform.SetParams( 0, m_fLineSpacing * -0.5 );
arrScales[i + 1].data.transform.SetParams( 1, 1 );
arrAlphas[i + 1].data.transform.SetParams( 1 );
arrAngles[i + 1].data.transform.SetParams( 0 );
arrMoves [i + 1].data.transform.SetParams( 0, 0 );
}
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
if( !pLetter->m_bNotLetter )
{
oManager.AddRotateTransforms( arrAngles, c_nPoints );
oManager.AddScaleTransforms( arrScales, c_nPoints );
oManager.AddTranslateTransforms( arrMoves, c_nPoints );
}
oManager.AddTransparencyTransforms( arrAlphas, c_nPoints );
oManager.SetTimeParams( nLetter, letters.count, letters.count * 3 );
}
}
// New2
void Boomerang( BOOL bPhaseIn )
{
float dx = m_pText->m_oPathBoundRect.Width / 2;
Text::Transforms::CTranslateTransforms::TData arrMoves[3];
arrMoves[0].data.transform.SetParams( dx, -dx );
arrMoves[1].data.transform.SetParams( dx/2, dx );
arrMoves[2].data.transform.SetParams( 0, 0 );
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddScale( 0.4, 1, 1, 1 );
oTextManager.AddRotate( -90, 0 );
oTextManager.AddTranslateTransforms( arrMoves, 3 );
oTextManager.AddFadeTransparency( 0, 1, 1, 5 );
}
void Flash( BOOL bPhaseIn )
{
double dx = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nLeftBound );
double dMin = 5 / m_fLineSpacing;
double dMax = 1.25;
Text::Transforms::CTranslateTransforms::TData arrMoves[5];
Text::Transforms::CScaleTransforms::TData arrScales[5];
arrMoves [0].data.transform.SetParams( dx, 0 );
arrScales[0].data.transform.SetParams( 1, dMin );
arrScales[1].data.transform.SetParams( dMax, dMin );
arrScales[2].data.transform.SetParams( 1, 1 );
arrScales[3].data.transform.SetParams( dMax, dMax );
arrScales[4].data.transform.SetParams( 1, 1 );
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTranslateTransforms( arrMoves, 5 );
oTextManager.AddScaleTransforms( arrScales, 5 );
oTextManager.AddFadeTransparency( 0, 1, 1, 8 );
}
void Flight( BOOL bPhaseIn )
{
float dx = m_pText->m_oPathBoundRect.Width / 2;
Text::Transforms::CRotateAtTransforms::TData arrAngles[3];
Text::Transforms::CTranslateTransforms::TData arrMoves[3];
arrAngles[0].data.transform.SetParams( -90, -dx, 0 );
arrAngles[1].data.transform.SetParams( 0, -dx, 0 );
arrAngles[2].data.transform.SetParams( 0, 0, 0 );
arrMoves[0].data.transform.SetParams( 2*dx, -dx/2 );
arrMoves[1].data.transform.SetParams( -dx/2, dx/2 );
arrMoves[2].data.transform.SetParams( 0, 0 );
arrAngles[1].duration = arrMoves[1].duration = 2;
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddRotateAtTransforms( arrAngles, 3 );
oTextManager.AddTranslateTransforms( arrMoves, 3 );
oTextManager.AddFadeTransparency( 0, 1, 1, 5 );
}
void Jump( BOOL bPhaseIn )
{
const int c_nPoints = 7;
Text::Transforms::CTranslateTransforms::TData arrMoves[c_nPoints];
Text::Transforms::CScaleTransforms::TData arrScales[c_nPoints];
float dx = m_oLayoutRect.X - m_pText->m_oPathBoundRect.X;
float dy = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nTopBound );
for( int i = 0; i < c_nPoints; i++ )
{
double factor = double(c_nPoints - 1 - i) / (c_nPoints - 1);
arrMoves [i].data.transform.SetParams( dx * factor, dy / (1<<i) * ((i + 1)%2) );
arrScales[i].data.transform.SetParams( 1, 0.5 * ((i + 1)%2 + 1) );
}
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTranslateTransforms( arrMoves, c_nPoints );
oTextManager.AddScaleTransforms( arrScales, c_nPoints );
oTextManager.AddTransparency( 0, 1, FALSE );
}
void Compress( BOOL bPhaseIn )
{
double scale = 3;
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddFadeTransparency( 0, 1 );
CRefLines lines( m_pText->m_arrLines );
for( ; lines.count > 0; --lines.count, ++lines.ptr )
{
CRefLetters letters( m_pText->m_arrLetters, lines.ptr->m_nFirstLetter, lines.ptr->m_nLength );
for( ; letters.count > 0; --letters.count, ++letters.ptr )
{
double dx = (1 - scale) * (letters.ptr->m_oPathBoundRect.Width / 2 + lines.ptr->m_oPathBoundRect.GetRight() - letters.ptr->m_oPathBoundRect.GetRight());
Text::Transforms::CTransformManager& oManager = letters.ptr->GetTransformManager( bPhaseIn );
oManager.AddScale( scale, 1, 1, 1 );
oManager.AddTranslate( dx, 0, 0, 0 );
}
}
}
void Motion( BOOL bPhaseIn )
{
double offset = m_pText->m_oPathBoundRect.GetRight() - m_oLayoutRect.X;
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
double dx = Utils::GetOffsetRect( m_oLayoutRect, pLetter->m_oPathBoundRect, Utils::c_nLeftBound );
if( pLetter->m_bNotLetter )
{
oManager.AddScale( abs(dx / offset), 1, 1, 1 );
}
oManager.AddTranslate( dx, 0, 0, 0 );
oManager.SetTimeParams( 0, abs(dx / offset) );
oManager.AddTransparency( 0, 1 );
}
}
void Manifestation( BOOL bPhaseIn )
{
double dy = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nTopBound );
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
oTextManager.AddScale( 0, 1 );
oTextManager.AddTranslate( 0, dy, 0, 0 );
}
void Shot( BOOL bPhaseIn )
{
Text::Transforms::CRotateTransforms::TData arrAngles[3];
Text::Transforms::CTranslateTransforms::TData arrMoves[3];
Text::Transforms::CScaleTransforms::TData arrScales[3];
double dy = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nTopBound );
double dx = m_pText->m_oPathBoundRect.Y - m_oLayoutRect.Y;
arrAngles[0].data.transform.SetParams( 90 );
arrAngles[1].data.transform.SetParams( 0 );
arrAngles[2].data.transform.SetParams( 0 );
arrMoves[0].data.transform.SetParams( dx, dy );
arrMoves[1].data.transform.SetParams( 0, m_fLineSpacing );
arrMoves[2].data.transform.SetParams( 0, 0 );
arrScales[0].data.transform.SetParams( 1, 1 );
arrScales[1].data.transform.SetParams( 0.1, 1 );
arrScales[2].data.transform.SetParams( 1, 1 );
arrAngles[1].duration = arrMoves[1].duration = arrScales[1].duration = 5;
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
arrScales[0].data.transform.dScaleX = !pLetter->m_bNotLetter ? 1 : m_fLineSpacing / pLetter->m_oPathBoundRect.Width;
oManager.AddScaleTransforms( arrScales, 3 );
oManager.AddRotateTransforms( arrAngles, 3 );
}
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTranslateTransforms( arrMoves, 3 );
oTextManager.AddFadeTransparency( 0, 1 );
}
void Reduction( BOOL bPhaseIn )
{
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
oManager.AddScale( 0.5, 10, 1, 1 );
oManager.AddFadeTransparency( 0, 1, 3, 2 );
oManager.SetTimeParams( nLetter, letters.count, letters.count * 0.33 );
}
}
void VHRotation( BOOL bPhaseIn )
{
Text::Transforms::CScaleTransforms::TData arrScalesX[7];
arrScalesX[0].data.transform.SetParams( -1, 1 );
arrScalesX[1].data.transform.SetParams( 0, 1 );
arrScalesX[2].data.transform.SetParams( 1, 1 );
arrScalesX[3].data.transform.SetParams( 0, 1 );
arrScalesX[4].data.transform.SetParams( -1, 1 );
arrScalesX[5].data.transform.SetParams( 0, 1 );
arrScalesX[6].data.transform.SetParams( 1, 1 );
Text::Transforms::CScaleTransforms::TData arrScalesY[7];
arrScalesY[0].data.transform.SetParams( 0.5, -2 );
arrScalesY[1].data.transform.SetParams( 1, 0 );
arrScalesY[2].data.transform.SetParams( 0.5, 2 );
arrScalesY[3].data.transform.SetParams( 1, 0 );
arrScalesY[4].data.transform.SetParams( 0.5, -2 );
arrScalesY[5].data.transform.SetParams( 1, 0 );
arrScalesY[6].data.transform.SetParams( 1, 1 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
oManager.AddScaleTransforms( (nLetter % 2) ? arrScalesX : arrScalesY, 7 );
}
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
}
void Rotate3D( BOOL bPhaseIn )
{
Text::Transforms::CScaleTransforms::TData arrScales[8];
Text::Transforms::CTranslateTransforms::TData arrMoves[8];
double dy = m_fLineSpacing * 1.5;
arrScales[0].data.transform.SetParams( 0.75, 0 );
arrScales[1].data.transform.SetParams( 0.50, -0.5 );
arrScales[2].data.transform.SetParams( 0.75, 0 );
arrScales[3].data.transform.SetParams( 1 , 1 );
arrScales[4].data.transform.SetParams( 0.75, 0 );
arrScales[5].data.transform.SetParams( 0.50, -0.5 );
arrScales[6].data.transform.SetParams( 0.75, 0 );
arrScales[7].data.transform.SetParams( 1 , 1 );
arrMoves[0].data.transform.SetParams( 0, -dy);
arrMoves[1].data.transform.SetParams( 0, 0 );
arrMoves[2].data.transform.SetParams( 0, dy);
arrMoves[3].data.transform.SetParams( 0, 0 );
arrMoves[4].data.transform.SetParams( 0, -dy);
arrMoves[5].data.transform.SetParams( 0, 0 );
arrMoves[6].data.transform.SetParams( 0, dy);
arrMoves[7].data.transform.SetParams( 0, 0 );
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddScaleTransforms( arrScales, 8 );
oTextManager.AddTranslateTransforms( arrMoves, 8 );
oTextManager.AddTransparency( 0, 1 );
}
void Spiral( BOOL bPhaseIn )
{
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
double dr = m_fLineSpacing * -2;
oTextManager.AddTranslate( dr, dr, 0, 0 );
oTextManager.AddRotate( -720, 0 );
oTextManager.AddTransparency( 0, 1 );
}
void Flag( BOOL bPhaseIn )
{
}
void Perpendicular( BOOL bPhaseIn )
{
Text::Transforms::CRotateTransforms::TData arrAngles[4];
Text::Transforms::CTranslateTransforms::TData arrMoves [4];
arrAngles[0].data.transform.SetParams( -90 );
arrAngles[1].data.transform.SetParams( -90 );
arrAngles[2].data.transform.SetParams( 0 );
arrAngles[3].data.transform.SetParams( 0 );
arrAngles[1].data.interpolation = FALSE;
arrAngles[3].data.interpolation = FALSE;
CRefLines lines( m_pText->m_arrLines );
for( ; lines.count > 0; --lines.count, ++lines.ptr )
{
double offset = lines.ptr->m_oPathBoundRect.Height / 2;
CRefLetters letters( m_pText->m_arrLetters, lines.ptr->m_nFirstLetter, lines.ptr->m_nLength );
for( ; letters.count > 0; --letters.count, ++letters.ptr )
{
double dx = lines.ptr->m_oPathBoundRect.X - letters.ptr->m_oPathCenter.X;
double dy = lines.ptr->m_oPathBoundRect.Width + dx + m_fLineSpacing;
arrMoves[0].data.transform.SetParams( dx - offset, dy + offset );
arrMoves[1].data.transform.SetParams( dx - offset, offset );
arrMoves[2].data.transform.SetParams( dx, 0 );
arrMoves[3].data.transform.SetParams( 0, 0 );
arrAngles[1].duration = arrMoves[1].duration = abs(dy);
arrAngles[2].duration = arrMoves[2].duration = offset * IPP_SQRT2;
arrAngles[3].duration = arrMoves[3].duration = abs(dx);
Text::Transforms::CTransformManager& oManager = letters.ptr->GetTransformManager( bPhaseIn );
oManager.AddRotateTransforms( arrAngles, 4 );
oManager.AddTranslateTransforms( arrMoves, 4 );
}
}
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddFadeTransparency( 0, 1, 1, 5 );
}
void Clock( BOOL bPhaseIn )
{
Text::Transforms::CTranslateTransforms::TData arrMoves[3];
Text::Transforms::CScaleTransforms::TData arrScales[3];
arrScales[0].data.transform.SetParams( 1.5, 1.5 );
arrScales[1].data.transform.SetParams( 1.5, 1.5 );
arrScales[2].data.transform.SetParams( 1.0, 1.0 );
arrMoves[0].data.interpolation = arrScales[1].data.interpolation = FALSE;
arrMoves[1].duration = 6; arrScales[1].duration = 5;
arrMoves[2].duration = 1; arrScales[2].duration = 1;
Gdiplus::PointF distance;
CRefLines lines( m_pText->m_arrLines );
for( ; lines.count > 0; --lines.count, ++lines.ptr )
{
CRefLetters letters( m_pText->m_arrLetters, lines.ptr->m_nFirstLetter, lines.ptr->m_nLength );
int nCenter = letters.count / 3;
CLetterEntity* pCenterLetter = letters.ptr + nCenter;
for( int nLetter = 0; nLetter < nCenter; nLetter++ )
{
arrMoves[0].data.transform.SetParams( m_fLineSpacing * -0.5, 0 );
arrMoves[1].data.transform.SetParams( m_fLineSpacing * -0.5, 0 );
distance = pCenterLetter->m_oPathCenter - letters[nLetter].m_oPathCenter;
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
oManager.AddTranslateTransforms( arrMoves, 3 );
oManager.AddRotateAt( -300, 0, distance.X, distance.Y );
}
for( int nLetter = nCenter + 1; nLetter < letters.count; nLetter++ )
{
arrMoves[0].data.transform.SetParams( m_fLineSpacing * 0.5, 0 );
arrMoves[1].data.transform.SetParams( m_fLineSpacing * 0.5, 0 );
distance = pCenterLetter->m_oPathCenter - letters[nLetter].m_oPathCenter;
Text::Transforms::CTransformManager& oManager = letters[nLetter].GetTransformManager( bPhaseIn );
oManager.AddTranslateTransforms( arrMoves, 3 );
oManager.AddRotateAt( -1000, 0, distance.X, distance.Y );
}
arrScales[0].data.transform.dScaleX = \
arrScales[1].data.transform.dScaleX = (!pCenterLetter->m_bNotLetter ? 1.5 : 1 );
Text::Transforms::CTransformManager& oManager = pCenterLetter->GetTransformManager( bPhaseIn );
oManager.AddScaleTransforms( arrScales, 3 );
}
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddFadeTransparency( 0, 1, 1, 5 );
}
// New3
void Galaxy( BOOL bPhaseIn )
{
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
double angle = abs(pLetter->m_oOrigin.X / m_pText->m_oPathBoundRect.Width * 360);
oManager.AddTranslate( pLetter->m_oOrigin.X * 3, pLetter->m_oOrigin.Y * 3, 0, 0 );
oManager.AddRotate( angle, 0 );
oManager.AddTranslate( -pLetter->m_oOrigin.X, -pLetter->m_oOrigin.Y, 0, 0 );
}
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
oTextManager.AddRotate( 90, 0 );
oTextManager.AddScale( 0, 1 );
}
void WaveRotate3D( BOOL bPhaseIn )
{
Text::Transforms::CScaleAtTransforms::TData arrScales[6];
float step = m_fLineSpacing / 2;
arrScales[0].data.transform.SetParams( 0.6, -0.5, 0, step * -2 );
arrScales[1].data.transform.SetParams( 0.6, -0.6, 0, 0 );
arrScales[2].data.transform.SetParams( 0.65, -0.3, 0, step * 2 );
arrScales[3].data.transform.SetParams( 0.8, 0.01, 0, step * 4 );
arrScales[4].data.transform.SetParams( 0.95, 0.6, 0, step * 2 );
arrScales[5].data.transform.SetParams( 1, 1, 0, 0 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
for( int i = 0 ; i < 6; i++ )
{
arrScales[i].data.transform.dX = pLetter->m_oOrigin.X;
}
oManager.AddScaleAtTransforms( arrScales, 6 );
oManager.AddFadeTransparency( 0, 1, 1, 1 );
oManager.SetTimeParams( nLetter, letters.count, letters.count * 0.3 );
}
}
void RandomJump( BOOL bPhaseIn )
{
const int c_nPoints = 10;
Text::Transforms::CTranslateTransforms::TData arrMoves [c_nPoints];
Text::Transforms::CScaleTransforms::TData arrScales[c_nPoints];
Text::Transforms::CRotateTransforms::TData arrAngles[c_nPoints];
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
if( !pLetter->m_bNotLetter )
{
int nStartIndex = rand() % (c_nPoints - 5);
for( int i = nStartIndex; i < c_nPoints - 1; i++ )
{
double dx = 0;
double dy = (rand() % 2) * m_fLineSpacing * Random( -1.5f, -0.3f );
arrMoves [i].data.transform.SetParams( dx, dy );
dx = Random( 0.0f, 2.0f );
dy = Random( 0.0f, 2.0f );
arrScales[i].data.transform.SetParams( dx, dy );
arrAngles[i].data.transform.SetParams( Random( -30.0f, 30.0f ) );
}
oManager.AddTranslateTransforms( arrMoves + nStartIndex, c_nPoints - nStartIndex );
oManager.AddScaleTransforms ( arrScales + nStartIndex, c_nPoints - nStartIndex );
oManager.AddRotateTransforms ( arrAngles + nStartIndex, c_nPoints - nStartIndex );
}
}
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
}
void Galaxy2( BOOL bPhaseIn )
{
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
double angle = abs(pLetter->m_oOrigin.X) / m_pText->m_oPathBoundRect.Width * 500;
oManager.AddScale( 1, 3, 1, 1 );
oManager.AddShear( -1, 0, 0, 0 );
oManager.AddTranslate( pLetter->m_oOrigin.X * 3, pLetter->m_oOrigin.Y * 3, 0, 0 );
oManager.AddScale( 0.4, 1 );
oManager.AddRotate( angle, 0 );
oManager.AddTranslate( -pLetter->m_oOrigin.X, -pLetter->m_oOrigin.Y, 0, 0 );
}
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddTransparency( 0, 1 );
oTextManager.AddRotate( 360, 0 );
}
void Roll( BOOL bPhaseIn )
{
double dx = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nLeftBound );
double dy = m_fLineSpacing * 0.1;
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
if( !pLetter->m_bNotLetter )
{
oManager.AddRotateAt( -1080, 0, dy, 0, dy, 0 );
}
}
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddFadeTransparency( 0, 1, 1, 5 );
oTextManager.AddTranslate( dx, 0, 0, 0 );
}
void Conga( BOOL bPhaseIn )
{
const int c_nPoints = 7;
Text::Transforms::CTranslateTransforms::TData arrMoves [c_nPoints];
Text::Transforms::CScaleTransforms::TData arrScales[c_nPoints];
double step = m_fLineSpacing * 0.5;
arrMoves[0].data.transform.SetParams( 0, step * -6 );
arrMoves[1].data.transform.SetParams( 0, 0 );
arrMoves[2].data.transform.SetParams( step, step );
arrMoves[3].data.transform.SetParams( step * 1.5, step / 2 );
arrMoves[4].data.transform.SetParams( step * 1.5, step / -2 );
arrMoves[5].data.transform.SetParams( -step, 0 );
arrMoves[6].data.transform.SetParams( 0, 0 );
arrScales[0].data.transform.SetParams( 1.2, 1.2 );
arrScales[1].data.transform.SetParams( 1.2, 1.2 );
arrScales[2].data.transform.SetParams( 0.8, 0.8 );
arrScales[3].data.transform.SetParams( 0.6, 0.6 );
arrScales[4].data.transform.SetParams( 0.6, 0.6 );
arrScales[5].data.transform.SetParams( 0.4, 0.4 );
arrScales[6].data.transform.SetParams( 1, 1 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
oManager.AddTranslateTransforms( arrMoves, c_nPoints );
oManager.AddScaleTransforms( arrScales, c_nPoints );
oManager.AddFadeTransparency( 0, 1, 1, c_nPoints );
oManager.SetTimeParams( nLetter, letters.count, letters.count * 0.5 );
}
}
void _Matrix( BOOL bPhaseIn )
{
}
void HotPinkSpin( BOOL bPhaseIn )
{
const int c_nPoints = 6;
Text::Transforms::CRotateTransforms::TData arrAngles[c_nPoints];
Text::Transforms::CScaleTransforms::TData arrScales[c_nPoints];
Text::Transforms::CShearTransforms::TData arrShears[c_nPoints];
arrAngles[0].data.transform.SetParams( 90 );
arrAngles[1].data.transform.SetParams( 45 );
arrAngles[2].data.transform.SetParams( 0 );
arrAngles[3].data.transform.SetParams( 0 );
arrAngles[4].data.transform.SetParams( 0 );
arrAngles[5].data.transform.SetParams( 0 );
arrShears[0].data.transform.SetParams( -2, 0 );
arrShears[1].data.transform.SetParams( -3, 0 );
arrShears[2].data.transform.SetParams( -4, 0 );
arrShears[3].data.transform.SetParams( -2.25, 0 );
arrShears[4].data.transform.SetParams( -0.5, 0 );
arrShears[5].data.transform.SetParams( 0, 0 );
arrScales[0].data.transform.SetParams( -3, 5 );
arrScales[1].data.transform.SetParams( -1, 5 );
arrScales[2].data.transform.SetParams( 1, 5 );
arrScales[3].data.transform.SetParams( 1, 4 );
arrScales[4].data.transform.SetParams( 1, 3 );
arrScales[5].data.transform.SetParams( 1, 1 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
oManager.AddRotateTransforms( arrAngles, c_nPoints );
if( !pLetter->m_bNotLetter )
{
oManager.AddShearTransforms ( arrShears, c_nPoints );
oManager.AddScaleTransforms ( arrScales, c_nPoints );
}
oManager.AddFadeTransparency( 0, 1, 1, c_nPoints );
oManager.SetTimeParams( nLetter, letters.count, c_nPoints );
}
}
void HopInJumpOut( BOOL bPhaseIn )
{
}
void ConJoin( BOOL bPhaseIn )
{
const int c_nPoints = 6;
Text::Transforms::CTranslateTransforms::TData arrMoves [c_nPoints];
Text::Transforms::CScaleTransforms::TData arrScales[c_nPoints];
arrMoves[0].data.transform.SetParams( 0, 0 );
arrMoves[1].data.transform.SetParams( 0, m_fLineSpacing );
arrScales[0].data.transform.SetParams( 3, 3 );
arrScales[1].data.transform.SetParams( 3, 3 );
arrScales[2].data.transform.SetParams( 0.65, -0.3 );
arrScales[3].data.transform.SetParams( 0.8, 0 );
arrScales[4].data.transform.SetParams( 0.95, 0.6 );
arrScales[5].data.transform.SetParams( 1, 1 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
arrMoves[0].data.transform.dX = pLetter->m_oOrigin.X * 0.2;
arrMoves[1].data.transform.dX = pLetter->m_oOrigin.X * 0.2;
oManager.AddTranslateTransforms( arrMoves, c_nPoints );
oManager.AddScaleTransforms( arrScales, c_nPoints );
oManager.AddFadeTransparency( 0, 1, 1, c_nPoints );
oManager.SetTimeParams( nLetter, letters.count, letters.count * 0.5 );
}
}
void HopsCotch( BOOL bPhaseIn )
{
const int c_nPoints = 5;
Text::Transforms::CTranslateTransforms::TData arrMoves [c_nPoints];
Text::Transforms::CScaleTransforms::TData arrScales[c_nPoints];
Text::Transforms::CRotateTransforms::TData arrAngles[c_nPoints];
double step = m_fLineSpacing * 0.1;
arrMoves[0].data.transform.SetParams( step * -5, 0 );
arrMoves[1].data.transform.SetParams( step * 10, 0 );
arrMoves[2].data.transform.SetParams( 0, 0 );
arrMoves[3].data.transform.SetParams( step * -1, 0 );
arrMoves[4].data.transform.SetParams( 0, 0 );
arrScales[0].data.transform.SetParams( 3, 3 );
arrScales[1].data.transform.SetParams( 3, 3 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
arrAngles[3].data.transform.dAngle = !pLetter->m_bNotLetter ? -50 : 0;
oManager.AddTranslateTransforms( arrMoves, c_nPoints );
oManager.AddScaleTransforms( arrScales, c_nPoints );
oManager.AddRotateTransforms( arrAngles, c_nPoints );
oManager.AddFadeTransparency( 0, 1, 1, c_nPoints );
oManager.SetTimeParams( nLetter, letters.count, letters.count * 0.3 );
}
}
void Twist( BOOL bPhaseIn )
{
}
void StarWars( BOOL bPhaseIn )
{
const int c_nPoints = 30;
Text::Transforms::CTransparencyTransforms::TData arrAlphas[3];
arrAlphas[0].data.transform.SetParams( 0 );
arrAlphas[1].data.transform.SetParams( 1 );
arrAlphas[2].data.transform.SetParams( 1 );
arrAlphas[1].data.interpolation = FALSE;
arrAlphas[1].duration = 5;
Text::Transforms::CTranslateTransforms::TData arrMoves1[c_nPoints];
Text::Transforms::CTranslateTransforms::TData arrMoves2[c_nPoints];
Text::Transforms::CShearTransforms::TData arrShears[c_nPoints];
Text::Transforms::CScaleTransforms::TData arrScales[c_nPoints];
CRefLines lines( m_pText->m_arrLines );
for( int nLine = 0; nLine < lines.count; nLine++ )
{
double dTop = Utils::GetOffsetRect( m_oLayoutRect, lines[nLine].m_oPathBoundRect, Utils::c_nTopBound );
double dBottom = Utils::GetOffsetRect( m_oLayoutRect, lines[nLine].m_oPathBoundRect, Utils::c_nBottomBound );
CRefLetters letters( m_pText->m_arrLetters, lines[nLine].m_nFirstLetter, lines[nLine].m_nLength );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
for( int i = 0; i < c_nPoints; i++ )
{
double dx = pLetter->m_oOrigin.X;
double sh = dx * 2 / m_pText->m_oPathBoundRect.Width;
double scale = 2 - 1.5 / double(c_nPoints) * i;
arrMoves1[i].data.transform.SetParams( dx, 0 );
arrShears[i].data.transform.SetParams( sh, 0 );
arrScales[i].data.transform.SetParams( scale, scale / 1.5);
arrMoves2[i].data.transform.SetParams( -dx, 0 );
}
oManager.AddTranslateTransforms( arrMoves1, c_nPoints );
oManager.AddShearTransforms( arrShears, c_nPoints );
oManager.AddScaleTransforms( arrScales, c_nPoints );
oManager.AddTranslateTransforms( arrMoves2, c_nPoints );
oManager.AddTransparencyTransforms( arrAlphas, 3 );
oManager.AddTranslate( 0, dBottom, 0, dTop );
oManager.SetTimeParams( nLine, lines.count, lines.count );
}
}
}
void Squeeze( BOOL bPhaseIn )
{
const int c_nPoints = 9;
Text::Transforms::CShearTransforms::TData arrShears[c_nPoints];
Text::Transforms::CScaleTransforms::TData arrScales[c_nPoints];
arrScales[0].data.transform.SetParams( 1, 1 );
arrScales[1].data.transform.SetParams( 0.75, 1 );
arrScales[2].data.transform.SetParams( 0.5, 1 );
arrScales[3].data.transform.SetParams( 0.75, 1 );
arrScales[4].data.transform.SetParams( 1, 1 );
arrScales[5].data.transform.SetParams( 0, 1 );
arrScales[6].data.transform.SetParams( -1, 1 );
arrScales[7].data.transform.SetParams( 0, 1 );
arrScales[8].data.transform.SetParams( 1, 1 );
arrShears[0].data.transform.SetParams( 0, 0 );
arrShears[1].data.transform.SetParams( 0, -0.25 );
arrShears[2].data.transform.SetParams( 0, -0.5 );
arrShears[3].data.transform.SetParams( 0, -0.25 );
arrShears[4].data.transform.SetParams( 0, 0 );
arrShears[5].data.transform.SetParams( 0, 1 );
arrShears[6].data.transform.SetParams( 0, 0 );
arrShears[7].data.transform.SetParams( 0, -1 );
arrShears[8].data.transform.SetParams( 0, 0 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
if( !pLetter->m_bNotLetter )
{
oManager.AddScaleTransforms( arrScales, c_nPoints );
oManager.AddShearTransforms( arrShears, c_nPoints );
}
}
double dx = Utils::GetOffsetRect( m_oLayoutRect, m_pText->m_oPathBoundRect, Utils::c_nLeftBound );
Text::Transforms::CTransformManager& oTextManager = m_pText->GetTransformManager( bPhaseIn );
oTextManager.AddFadeTransparency( 0, 1, 1, 5 );
oTextManager.AddTranslate( dx, 0, 0, 0 );
}
void Terminator( BOOL bPhaseIn )
{
const int c_nPoints = 5;
Text::Transforms::CScaleAtTransforms::TData arrScales[c_nPoints];
arrScales[0].data.transform.SetParams( 0, 0, 0, 0 );
arrScales[1].data.transform.SetParams( 0.01, 0.1, 0, 0 );
arrScales[2].data.transform.SetParams( 1, 0.1, 0, 0 );
arrScales[3].data.transform.SetParams( 1, 0.1, 0, 0 );
arrScales[4].data.transform.SetParams( 1, 1, 0, 0 );
CRefLetters letters( m_pText->m_arrLetters );
for( int nLetter = 0; nLetter < letters.count; nLetter++ )
{
Text::CLetterEntity* pLetter = letters.ptr + nLetter;
Text::Transforms::CTransformManager& oManager = pLetter->GetTransformManager( bPhaseIn );
arrScales[0].data.transform.dX = \
arrScales[1].data.transform.dX = \
arrScales[2].data.transform.dX = \
arrScales[3].data.transform.dX = pLetter->m_oOrigin.X;
oManager.AddScaleAtTransforms( arrScales, c_nPoints );
}
}
};
}
}
}