#pragma once #include #include 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 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, 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, 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, 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, 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, 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, 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 { public: void AddToFactor( double& factor, double dTime ) { CTransparency transparency; Interpolate( transparency, dTime ); factor *= transparency.dFactor; } }; class CTransformManager { protected: ATL::CSimpleArray m_arrpGeometryTransforms; ATL::CSimpleArray 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 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 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 oPathPoints( nPointCount + 1 ); CBuffer oPathTypes( nPointCount + 1 ); CBuffer 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 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 m_arrLetters; // список букв CAtlArray 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 CRefLines; class CTextPainter2 : public ImageStudio::Caching::CCacheItemPointer { protected: CTextEntity* m_pText; CAtlArray 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( ®ion, 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<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 ); } } }; } } }