mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-15 19:03:05 +08:00
1176 lines
25 KiB
C++
1176 lines
25 KiB
C++
#pragma once
|
|
|
|
#include <atlstr.h>
|
|
#include <atlcoll.h>
|
|
#include <atlenc.h>
|
|
#include <math.h>
|
|
|
|
// êîíâåðòàöèÿ: ìèëëèìåòðû â êîîðäèíàòû PDF
|
|
|
|
template <typename T>
|
|
inline double MMToPDFCoords( T tMM )
|
|
{
|
|
return ( tMM / 25.4 ) * 72.0;
|
|
}
|
|
template <typename T>
|
|
inline double PDFCoordsToMM( T tX )
|
|
{
|
|
return ( tX / 72.0 ) * 25.4;
|
|
}
|
|
|
|
template <typename T>
|
|
inline double PxToMM( T tX )
|
|
{
|
|
return tX * 25.4 / 96;
|
|
}
|
|
|
|
|
|
// Ñëåäóþùèå êëàññû âçÿòû èç AVSOfficeSWFRenderer.
|
|
enum ERendererState
|
|
{
|
|
rendstateNone = 0, // Âñå òåêóùèå êîìàíäû çàêîí÷åíû
|
|
rendstateText = 1, // Èäåò íàáèâêà òåêñò
|
|
rendstatePath = 2, // Èäåò íàáèâêà ïàòà
|
|
rendstateClipPath = 3, // Èäåò íàáèâêà ïàòà äëÿ êëèïà
|
|
rendstateClipText = 4, // Èäåò íàáèâêà òåêñòà äëÿ êëèïà
|
|
rendstateClipReset = 5, // Óäàëÿåì êëèï
|
|
rendstateImage = 6, // Îáðàáîòêà èçîáðàæåíèÿ
|
|
};
|
|
|
|
struct TMatrix
|
|
{
|
|
float fA;
|
|
float fB;
|
|
float fC;
|
|
float fD;
|
|
float fE;
|
|
float fF;
|
|
|
|
void Set(float fNewA, float fNewB, float fNewC, float fNewD, float fNewE, float fNewF)
|
|
{
|
|
fA = fNewA;
|
|
fB = fNewB;
|
|
fC = fNewC;
|
|
fD = fNewD;
|
|
fE = fNewE;
|
|
fF = fNewF;
|
|
}
|
|
};
|
|
|
|
struct TCommandParams
|
|
{
|
|
double dAngle;
|
|
double dLeft;
|
|
double dTop;
|
|
double dWidth;
|
|
double dHeight;
|
|
DWORD nFlag;
|
|
|
|
TMatrix oMatrix;
|
|
};
|
|
|
|
struct TCommandType
|
|
{
|
|
int nType; // Òèï êîìàíäû
|
|
DWORD nFlag; // Ôëàãè, äëÿ äàííîé êîìàíäû
|
|
TCommandType *pPrev; // Óêàçàòåëü íà ïðåäûäóùóþ êîìàíäó â ñòåêå
|
|
};
|
|
|
|
class CMatrix
|
|
{
|
|
public:
|
|
|
|
CMatrix()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
CMatrix(double dA, double dB, double dC, double dD, double dE, double dF)
|
|
{
|
|
Set( dA, dB, dC, dD, dE, dF );
|
|
}
|
|
void Reset()
|
|
{
|
|
m_dA = 1;
|
|
m_dB = 0;
|
|
m_dC = 0;
|
|
m_dD = 1;
|
|
m_dE = 0;
|
|
m_dF = 0;
|
|
|
|
m_dRotate = 0;
|
|
m_dSkewX = 0;
|
|
m_dSkewY = 0;
|
|
m_dScaleX = 1;
|
|
m_dScaleY = 1;
|
|
}
|
|
|
|
void Set(double dA, double dB, double dC, double dD, double dE, double dF)
|
|
{
|
|
m_dA = dA;
|
|
m_dB = dB;
|
|
m_dC = dC;
|
|
m_dD = dD;
|
|
m_dE = dE;
|
|
m_dF = dF;
|
|
|
|
Split2();
|
|
}
|
|
|
|
|
|
template <typename T> void DoTransform(T &tX, T &tY)
|
|
{
|
|
T tOldX = tX, tOldY = tY;
|
|
|
|
tX = tOldX * m_dA + tOldY * m_dC + m_dE;
|
|
tY = tOldX * m_dB + tOldY * m_dD + m_dF;
|
|
}
|
|
|
|
// Â äàííîì ïðåîáðàçîâàíèè íå äåëàåòñÿ ïåðåíîñ
|
|
template <typename T> void DoTransform2(T &tX, T &tY)
|
|
{
|
|
T tOldX = tX, tOldY = tY;
|
|
|
|
tX = tOldX * m_dA + tOldY * m_dC;
|
|
tY = tOldX * m_dB + tOldY * m_dD;
|
|
}
|
|
|
|
template <typename T> void DoITransform(T &tX, T &tY)
|
|
{
|
|
double dDet = m_dA * m_dD - m_dB * m_dC;
|
|
if ( fabs( dDet ) < 0.001 )
|
|
return;
|
|
|
|
// Îáðàòíàÿ ìàòðèöà
|
|
// | d -b 0 |
|
|
// det^(-1) * | -c a 0 |
|
|
// | c*f - d*e b*e - a*f 1 |
|
|
|
|
double dIDet = 1 / dDet;
|
|
double dIDet_2 = dIDet * dIDet;
|
|
|
|
|
|
|
|
T tOldX = tX, tOldY = tY;
|
|
|
|
tX = dIDet * ( tOldX * m_dD - tOldY * m_dC + m_dC * m_dF - m_dD * m_dE );
|
|
tY = dIDet * (-tOldX * m_dB + tOldY * m_dA + m_dB * m_dE - m_dA * m_dF );
|
|
}
|
|
template <typename T> void DoITransform2(T &tX, T &tY)
|
|
{
|
|
double dDet = m_dA * m_dD - m_dB * m_dC;
|
|
if ( fabs( dDet ) < 0.001 )
|
|
return;
|
|
|
|
// Îáðàòíàÿ ìàòðèöà
|
|
// | d -b 0 |
|
|
// det^(-1) * |-c a 0 |
|
|
// | 0 0 1 |
|
|
|
|
double dIDet = 1 / dDet;
|
|
|
|
T tOldX = tX, tOldY = tY;
|
|
|
|
tX = dIDet * ( tOldX * m_dD - tOldY * m_dC );
|
|
tY = dIDet * (-tOldX * m_dB + tOldY * m_dA );
|
|
}
|
|
double get_Rotate() const
|
|
{
|
|
return m_dRotate;
|
|
}
|
|
|
|
double get_SkewX() const
|
|
{
|
|
return m_dSkewX;
|
|
}
|
|
double get_SkewY() const
|
|
{
|
|
return m_dSkewY;
|
|
}
|
|
|
|
double get_ScaleX() const
|
|
{
|
|
return m_dScaleX;
|
|
}
|
|
|
|
double get_ScaleY() const
|
|
{
|
|
return m_dScaleY;
|
|
}
|
|
|
|
double get_A() const
|
|
{
|
|
return m_dA;
|
|
}
|
|
double get_B() const
|
|
{
|
|
return m_dB;
|
|
}
|
|
double get_C() const
|
|
{
|
|
return m_dC;
|
|
}
|
|
double get_D() const
|
|
{
|
|
return m_dD;
|
|
}
|
|
|
|
double get_E() const
|
|
{
|
|
return m_dE;
|
|
}
|
|
double get_F() const
|
|
{
|
|
return m_dF;
|
|
}
|
|
private:
|
|
|
|
void Split()
|
|
{
|
|
m_dScaleX = sqrt( m_dA * m_dA + m_dB * m_dB );
|
|
m_dScaleY = sqrt( m_dC * m_dC + m_dD * m_dD );
|
|
|
|
double dX_0 = 0;
|
|
double dY_0 = 1;
|
|
|
|
DoTransform2( dX_0, dY_0 );
|
|
|
|
double dX_1 = 1;
|
|
double dY_1 = 0;
|
|
|
|
DoTransform2( dX_1, dY_1 );
|
|
|
|
m_dSkewX = atan2( dY_0, dX_0 ) - 1.57079632675;
|
|
m_dSkewY = atan2( dY_1, dX_1 );
|
|
|
|
m_dRotate = m_dSkewX;
|
|
}
|
|
|
|
void Split2()
|
|
{
|
|
// Äàííàÿ ôóíêöèÿ ðàáîòàåò ñïåöèàëüíî ïîä SWF::Matrix::ComputeMatrix
|
|
m_dRotate = 0;
|
|
m_dScaleX = m_dA;
|
|
m_dSkewX = m_dB;
|
|
m_dSkewY = m_dC;
|
|
m_dScaleY = m_dD;
|
|
}
|
|
|
|
private:
|
|
|
|
double m_dA; //
|
|
double m_dB; // Ìàòðèöà ïðåîáðàçîâàíèÿ
|
|
double m_dC; // | a b 0 |
|
|
double m_dD; // | c d 0 |
|
|
double m_dE; // | e f 1 |
|
|
double m_dF; //
|
|
|
|
double m_dRotate; // Óãîë ïîâîðîòà
|
|
|
|
double m_dSkewX; // Êîýôôèöèåíòû èñêîæåíèÿ
|
|
double m_dSkewY; //
|
|
|
|
double m_dScaleX; // Êîýôôèöèåíòû ñæàòèÿ/ðàñøèðåíèÿ
|
|
double m_dScaleY; // ïî îñÿì oX,oY
|
|
};
|
|
class CRendererState
|
|
{
|
|
public:
|
|
|
|
struct TMatrix
|
|
{
|
|
double dA;
|
|
double dB;
|
|
double dC;
|
|
double dD;
|
|
double dE;
|
|
double dF;
|
|
|
|
void Reset()
|
|
{
|
|
dA = 1; dB = 0;
|
|
dC = 0; dD = 1;
|
|
dE = 0; dF = 0;
|
|
}
|
|
|
|
void Set(double d_A, double d_B, double d_C, double d_D, double d_E, double d_F )
|
|
{
|
|
dA = d_A; dB = d_B;
|
|
dC = d_C; dD = d_D;
|
|
dE = d_E; dF = d_F;
|
|
}
|
|
};
|
|
|
|
public:
|
|
|
|
CRendererState()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
~CRendererState()
|
|
{
|
|
}
|
|
|
|
void Reset()
|
|
{
|
|
m_eState = rendstateNone;
|
|
m_ePrevState = rendstateNone;
|
|
|
|
m_oMatrix.Reset();
|
|
m_oPrevMatrix.Reset();
|
|
}
|
|
|
|
ERendererState get_State() const
|
|
{
|
|
return m_eState;
|
|
}
|
|
ERendererState get_PrevState() const
|
|
{
|
|
return m_ePrevState;
|
|
}
|
|
|
|
const TMatrix &get_PrevMatrix() const
|
|
{
|
|
return m_oPrevMatrix;
|
|
}
|
|
void set_NewState(ERendererState eState, CMatrix oMatrix)
|
|
{
|
|
m_ePrevState = m_eState;
|
|
m_oPrevMatrix = m_oMatrix;
|
|
|
|
m_eState = eState;
|
|
m_oMatrix.Set( oMatrix.get_A(), oMatrix.get_B(), oMatrix.get_C(), oMatrix.get_D(), oMatrix.get_E(), oMatrix.get_F() );
|
|
}
|
|
|
|
// Ïðîâåðÿåì, èçìåíèëàñü ëè ìàòðèöà ïðåîáðàçîâàíèé
|
|
bool IsMatrixChanged()
|
|
{
|
|
if ( m_ePrevState == rendstateNone )
|
|
return false;
|
|
|
|
return ( fabs( m_oMatrix.dA - m_oPrevMatrix.dA ) > 0.001 || fabs( m_oMatrix.dB - m_oPrevMatrix.dB ) > 0.001 || fabs( m_oMatrix.dC - m_oPrevMatrix.dC ) > 0.001 || fabs( m_oMatrix.dD - m_oPrevMatrix.dD ) > 0.001 || fabs( m_oMatrix.dE - m_oPrevMatrix.dE ) > 0.001 || fabs( m_oMatrix.dF - m_oPrevMatrix.dF ) > 0.001 );
|
|
}
|
|
|
|
// Ïðîâåðÿåì èçìåíèëàñü ëè ãëàâíàÿ ÷àñòü ìàòðèöû ïðåîáðàçîâàíèé
|
|
bool IsMatrixChanged2()
|
|
{
|
|
if ( m_ePrevState == rendstateNone )
|
|
return false;
|
|
|
|
return ( fabs( m_oMatrix.dA - m_oPrevMatrix.dA ) > 0.001 || fabs( m_oMatrix.dB - m_oPrevMatrix.dB ) > 0.001 || fabs( m_oMatrix.dC - m_oPrevMatrix.dC ) > 0.001 || fabs( m_oMatrix.dD - m_oPrevMatrix.dD ) > 0.001 );
|
|
}
|
|
|
|
void change_State(ERendererState eState)
|
|
{
|
|
m_eState = eState;
|
|
}
|
|
private:
|
|
|
|
ERendererState m_eState; // Òåêóùåå ñîñòîÿíèå
|
|
ERendererState m_ePrevState; // Ïðåäûäóùåå ñîñòîÿíèå
|
|
|
|
TMatrix m_oMatrix; // Òåêóùàÿ ìàòðèöà
|
|
TMatrix m_oPrevMatrix; // Ìàòðèöà ïðåäûäóùåãî ñîñòîÿíèÿ
|
|
|
|
// TO DO: Äîáàâèòü, åñëè íàäî, äîïîëíèòåëüíûå ïàðàìåòðû
|
|
|
|
};
|
|
class CContiniousText
|
|
{
|
|
public:
|
|
|
|
struct TColor
|
|
{
|
|
unsigned char unR;
|
|
unsigned char unG;
|
|
unsigned char unB;
|
|
unsigned char unA;
|
|
};
|
|
struct TMatrix
|
|
{
|
|
double dA;
|
|
double dB;
|
|
double dC;
|
|
double dD;
|
|
double dE;
|
|
double dF;
|
|
|
|
void Reset()
|
|
{
|
|
dA = 1; dB = 0;
|
|
dC = 0; dD = 1;
|
|
dE = 0; dF = 0;
|
|
}
|
|
void Set(double d_A, double d_B, double d_C, double d_D, double d_E, double d_F)
|
|
{
|
|
dA = d_A; dB = d_B;
|
|
dC = d_C; dD = d_D;
|
|
dE = d_E; dF = d_F;
|
|
}
|
|
};
|
|
|
|
struct TText
|
|
{
|
|
BSTR bsText;
|
|
BSTR bsUnicodeText;
|
|
float fX;
|
|
float fY;
|
|
float fWidth;
|
|
float fHeight;
|
|
float fBaseLineOffset;
|
|
bool bStringGID;
|
|
};
|
|
|
|
|
|
public:
|
|
|
|
CContiniousText()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
~CContiniousText()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
void Reset()
|
|
{
|
|
m_bFirstEntry = TRUE;
|
|
m_fX = 0;
|
|
m_fY = 0;
|
|
m_oMatrix.Reset();
|
|
|
|
for ( int nIndex = 0; nIndex < m_arrTexts.GetSize(); nIndex++ )
|
|
{
|
|
::SysFreeString( m_arrTexts[nIndex].bsText );
|
|
::SysFreeString( m_arrTexts[nIndex].bsUnicodeText );
|
|
}
|
|
|
|
m_arrTexts .RemoveAll();
|
|
m_arrFonts .RemoveAll();
|
|
m_arrColors .RemoveAll();
|
|
m_arrMatrixes.RemoveAll();
|
|
m_arrCharSpacing.RemoveAll();
|
|
}
|
|
void Add(CString sText, CString sUnicodeText, float fX, float fY, float fWidth, float fHeight, float fLineOffset, bool bStringGID, NSStructures::CFont oFont, NSStructures::CBrush oBrush, CMatrix oMatrix, double dCharSpacing)
|
|
{
|
|
TText oText;
|
|
m_arrTexts.Add( oText );
|
|
|
|
double dX = MMToPDFCoords( fX );
|
|
double dY = MMToPDFCoords( fY );
|
|
double dWidth = MMToPDFCoords( fWidth );
|
|
double dHeight = MMToPDFCoords( fHeight );
|
|
double dLineOffset = MMToPDFCoords( fLineOffset );
|
|
|
|
int nLast = m_arrTexts.GetSize() - 1;
|
|
m_arrTexts[nLast].bsText = sText.AllocSysString();
|
|
m_arrTexts[nLast].bsUnicodeText = sUnicodeText.AllocSysString();
|
|
m_arrTexts[nLast].fX = dX;
|
|
m_arrTexts[nLast].fY = dY;
|
|
m_arrTexts[nLast].fWidth = dWidth;
|
|
m_arrTexts[nLast].fHeight = dHeight;
|
|
m_arrTexts[nLast].fBaseLineOffset = dLineOffset;
|
|
m_arrTexts[nLast].bStringGID = bStringGID;
|
|
|
|
TMatrix oNewMatrix;
|
|
oNewMatrix.Set( oMatrix.get_A(), oMatrix.get_B(), oMatrix.get_C(), oMatrix.get_D(), oMatrix.get_E(), oMatrix.get_F() );
|
|
|
|
TColor oColor;
|
|
oColor.unR = (unsigned char) ( ( oBrush.Color1 & 0x000000FF ) );
|
|
oColor.unG = (unsigned char) ( ( oBrush.Color1 & 0x0000FF00 ) >> 8 );
|
|
oColor.unB = (unsigned char) ( ( oBrush.Color1 & 0x00FF0000 ) >> 16 );
|
|
oColor.unA = (unsigned char) ( oBrush.Alpha1 );
|
|
|
|
m_arrColors .Add( oColor );
|
|
m_arrFonts .Add( oFont );
|
|
m_arrMatrixes .Add( oNewMatrix );
|
|
m_arrCharSpacing.Add( dCharSpacing );
|
|
|
|
if ( m_bFirstEntry )
|
|
{
|
|
m_bFirstEntry = FALSE;
|
|
|
|
m_fX = dX;
|
|
m_fY = dY;
|
|
m_oMatrix = oMatrix;
|
|
}
|
|
}
|
|
|
|
int GetSize()
|
|
{
|
|
int nSize = m_arrTexts.GetSize();
|
|
if ( nSize == m_arrMatrixes.GetSize() && nSize == m_arrFonts.GetSize() && nSize == m_arrCharSpacing.GetSize() && nSize == m_arrColors.GetSize() )
|
|
return nSize;
|
|
|
|
return -1;
|
|
}
|
|
void LeaveLast()
|
|
{
|
|
// Îñòàâëÿåì ïîñëåäíþþ çàïèñü. Ýòî ïðèìåíÿåòñÿ, êîãäà ó ïîñëåäíåé
|
|
// çàïèñè íîâàÿ ìàòðèöà ïðåîáðàçîâàíèÿ.
|
|
|
|
int nSize = m_arrTexts.GetSize() - 1;
|
|
for ( int nIndex = 0; nIndex < nSize; nIndex++ )
|
|
{
|
|
::SysFreeStringHelper( m_arrTexts[0].bsText );
|
|
|
|
m_arrTexts .RemoveAt( 0 );
|
|
m_arrFonts .RemoveAt( 0 );
|
|
m_arrColors .RemoveAt( 0 );
|
|
m_arrMatrixes.RemoveAt( 0 );
|
|
m_arrCharSpacing.RemoveAt( 0 );
|
|
}
|
|
|
|
if ( 1 == m_arrTexts.GetSize() )
|
|
{
|
|
m_bFirstEntry = FALSE;
|
|
|
|
m_fX = m_arrTexts[0].fX;
|
|
m_fY = m_arrTexts[0].fY;
|
|
|
|
m_oMatrix.Set( m_arrMatrixes[0].dA, m_arrMatrixes[0].dB, m_arrMatrixes[0].dC, m_arrMatrixes[0].dD, m_arrMatrixes[0].dE, m_arrMatrixes[0].dF );
|
|
}
|
|
else
|
|
{
|
|
m_bFirstEntry = TRUE;
|
|
|
|
m_fX = 0;
|
|
m_fY = 0;
|
|
|
|
m_oMatrix.Reset();
|
|
}
|
|
|
|
}
|
|
|
|
const CMatrix &get_Matrix () const
|
|
{
|
|
return m_oMatrix;
|
|
}
|
|
const float &get_X() const
|
|
{
|
|
return m_fX;
|
|
}
|
|
|
|
const float &get_Y() const
|
|
{
|
|
return m_fY;
|
|
}
|
|
|
|
const TText *get_Text (int nIndex) const
|
|
{
|
|
if ( nIndex >= 0 && nIndex < m_arrTexts.GetSize() )
|
|
return (m_arrTexts.GetData() + nIndex);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const NSStructures::CFont *get_Font (int nIndex) const
|
|
{
|
|
if ( nIndex >= 0 && nIndex < m_arrTexts.GetSize() )
|
|
return (m_arrFonts.GetData() + nIndex);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
const TColor *get_Color (int nIndex) const
|
|
{
|
|
if ( nIndex >= 0 && nIndex < m_arrTexts.GetSize() )
|
|
return (m_arrColors.GetData() + nIndex);
|
|
|
|
return NULL;
|
|
}
|
|
const double get_CharSp (int nIndex) const
|
|
{
|
|
if ( nIndex >= 0 && nIndex < m_arrTexts.GetSize() )
|
|
return m_arrCharSpacing[nIndex];
|
|
|
|
return 0;
|
|
}
|
|
private:
|
|
|
|
BOOL m_bFirstEntry;
|
|
|
|
float m_fX; // Êîîðäèíàòû ïåðâîãî òåêñòà
|
|
float m_fY; //
|
|
CMatrix m_oMatrix; // Ìàòðèöà ïåðâîãî òåêñòà
|
|
|
|
CSimpleArray<TText > m_arrTexts; // Ñïèñîê òåêñòîâ
|
|
CSimpleArray<NSStructures::CFont> m_arrFonts; // Ñïèñîê øðèôòîâ ê òåêñòàì
|
|
CSimpleArray<TColor > m_arrColors; // Ñïèñîê òåêñòîâûõ öâåòîâ
|
|
CSimpleArray<TMatrix > m_arrMatrixes; // Ñïèñîê ìàòðèö ê òåêñòàì ( â ìàòðèöàõ èçìåíÿòüñÿ äîëæíî òîëüêî ñìåùåíèå )
|
|
CSimpleArray<double > m_arrCharSpacing; // Ìåæñèìâîëüíûé èíòåðâàë
|
|
};
|
|
class CFontLoader
|
|
{
|
|
public:
|
|
CFontLoader()
|
|
{
|
|
}
|
|
~CFontLoader()
|
|
{
|
|
}
|
|
void Add(CString sFilePath, CString sFontName, CString sEncodingName, CString sToUnicodeName )
|
|
{
|
|
m_arrFilePath.Add( sFilePath );
|
|
m_arrFontName.Add( sFontName );
|
|
m_arrEncodingName.Add( sEncodingName );
|
|
m_arrToUnicodeName.Add( sToUnicodeName );
|
|
|
|
m_mPathMap.SetAt( sFilePath, m_arrFilePath.GetCount() - 1 );
|
|
}
|
|
BOOL Find(CString sFilePath, CString *psFontName, CString *psEncodingName, CString *psToUnicodeName)
|
|
{
|
|
CAtlMap<CString, int>::CPair* pEl = m_mPathMap.Lookup( sFilePath );
|
|
|
|
if ( NULL != pEl )
|
|
{
|
|
int nIndex = pEl->m_value;
|
|
*psFontName = m_arrFontName.GetAt( nIndex );
|
|
*psEncodingName = m_arrEncodingName.GetAt( nIndex );
|
|
*psToUnicodeName = m_arrToUnicodeName.GetAt( nIndex );
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
private:
|
|
|
|
CAtlMap<CString, int> m_mPathMap;
|
|
CAtlArray<CString> m_arrFilePath;
|
|
CAtlArray<CString> m_arrFontName;
|
|
CAtlArray<CString> m_arrEncodingName;
|
|
CAtlArray<CString> m_arrToUnicodeName;
|
|
};
|
|
class CFindFonts
|
|
{
|
|
public:
|
|
CFindFonts()
|
|
{
|
|
m_pFontName = NULL;
|
|
m_pFontFile = NULL;
|
|
|
|
m_pBoldOut = NULL;
|
|
m_pItalicOut = NULL;
|
|
|
|
m_pBoldIn = NULL;
|
|
m_pItalicIn = NULL;
|
|
|
|
m_nCount = 0;
|
|
m_nSize = 0;
|
|
}
|
|
~CFindFonts()
|
|
{
|
|
if ( m_pFontName )
|
|
{
|
|
for ( int nIndex = 0; nIndex < m_nCount; nIndex++ )
|
|
{
|
|
::SysFreeString( m_pFontName[nIndex] );
|
|
}
|
|
free( m_pFontName );
|
|
m_pFontName = NULL;
|
|
}
|
|
|
|
if ( m_pFontFile )
|
|
{
|
|
for ( int nIndex = 0; nIndex < m_nCount; nIndex++ )
|
|
{
|
|
::SysFreeString( m_pFontFile[nIndex] );
|
|
}
|
|
free( m_pFontFile );
|
|
m_pFontFile = NULL;
|
|
}
|
|
|
|
if ( m_pBoldOut )
|
|
{
|
|
free( m_pBoldOut );
|
|
m_pBoldOut = NULL;
|
|
}
|
|
|
|
if ( m_pItalicOut )
|
|
{
|
|
free( m_pItalicOut );
|
|
m_pItalicOut = NULL;
|
|
}
|
|
|
|
if ( m_pBoldIn )
|
|
{
|
|
free( m_pBoldIn );
|
|
m_pBoldIn = NULL;
|
|
}
|
|
|
|
if ( m_pItalicIn )
|
|
{
|
|
free( m_pItalicIn );
|
|
m_pItalicIn = NULL;
|
|
}
|
|
|
|
m_nCount = 0;
|
|
m_nSize = 0;
|
|
}
|
|
|
|
void Add(CString sFontName, CString sFontFile, BOOL bBoldIn, BOOL bItalicIn, BOOL bBoldOut, BOOL bItalicOut)
|
|
{
|
|
Resize(1);
|
|
|
|
m_pFontName[m_nCount] = sFontName.AllocSysString();
|
|
m_pFontFile[m_nCount] = sFontFile.AllocSysString();
|
|
|
|
m_pBoldIn[m_nCount] = bBoldIn;
|
|
m_pItalicIn[m_nCount] = bItalicIn;
|
|
|
|
m_pBoldOut[m_nCount] = bBoldOut;
|
|
m_pItalicOut[m_nCount] = bItalicOut;
|
|
|
|
++m_nCount;
|
|
return;
|
|
}
|
|
|
|
BOOL Find(CString sFontName, BSTR *pbsFontFile, BOOL *pbBold, BOOL *pbItalic)
|
|
{
|
|
for ( int nIndex = 0; nIndex < m_nCount; ++nIndex )
|
|
{
|
|
if ( sFontName == CString(m_pFontName[nIndex]) && *pbBold == m_pBoldIn[nIndex] && *pbItalic == m_pItalicIn[nIndex] )
|
|
{
|
|
*pbsFontFile = m_pFontFile[nIndex];
|
|
|
|
*pbBold = m_pBoldOut[nIndex];
|
|
*pbItalic = m_pItalicOut[nIndex];
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
private:
|
|
|
|
void Resize(int nCount)
|
|
{
|
|
if ( m_nCount + nCount > m_nSize )
|
|
{
|
|
if ( m_nSize == 0 )
|
|
{
|
|
m_nSize = 32;
|
|
}
|
|
while ( m_nSize < m_nCount + nCount )
|
|
{
|
|
m_nSize *= 2;
|
|
}
|
|
|
|
m_pFontName = (BSTR *)realloc( m_pFontName, m_nSize * sizeof(BSTR));
|
|
m_pFontFile = (BSTR *)realloc( m_pFontFile, m_nSize * sizeof(BSTR));
|
|
|
|
m_pBoldOut = (BOOL *)realloc( m_pBoldOut, m_nSize * sizeof(BOOL));
|
|
m_pItalicOut = (BOOL *)realloc( m_pItalicOut, m_nSize * sizeof(BOOL));
|
|
|
|
m_pBoldIn = (BOOL *)realloc( m_pBoldIn, m_nSize * sizeof(BOOL));
|
|
m_pItalicIn = (BOOL *)realloc( m_pItalicIn, m_nSize * sizeof(BOOL));
|
|
}
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
BSTR *m_pFontName;
|
|
BSTR *m_pFontFile;
|
|
|
|
BOOL *m_pBoldIn;
|
|
BOOL *m_pItalicIn;
|
|
|
|
BOOL *m_pBoldOut;
|
|
BOOL *m_pItalicOut;
|
|
|
|
int m_nCount;
|
|
int m_nSize;
|
|
};
|
|
class CGdiPath
|
|
{
|
|
public:
|
|
|
|
static const int c_nTextureBrush = 3008;
|
|
|
|
public:
|
|
CGdiPath()
|
|
{
|
|
m_pPath = NULL;
|
|
}
|
|
~CGdiPath()
|
|
{
|
|
Delete();
|
|
}
|
|
|
|
void Create()
|
|
{
|
|
if ( m_pPath )
|
|
Delete();
|
|
m_pPath = new Gdiplus::GraphicsPath(Gdiplus::FillModeWinding);
|
|
}
|
|
void Delete()
|
|
{
|
|
RELEASEOBJECT( m_pPath );
|
|
}
|
|
|
|
void GetBounds(float *pfX, float *pfY, float *pfWidth, float *pfHeight)
|
|
{
|
|
if ( !CheckValidate() )
|
|
return;
|
|
|
|
Gdiplus::RectF oPathBounds;
|
|
m_pPath->GetBounds( &oPathBounds );
|
|
|
|
*pfX = oPathBounds.GetLeft();
|
|
*pfY = oPathBounds.GetTop();
|
|
*pfWidth = oPathBounds.GetRight() - oPathBounds.GetLeft();
|
|
*pfHeight = oPathBounds.GetBottom() - oPathBounds.GetTop();
|
|
}
|
|
// Ôóíêöèè äëÿ ñîñòàâëåíèÿ Path (òàê æå êàê è â IAVSOfficeRendererTemplate)
|
|
inline STDMETHOD(MoveTo)(float fX, float fY)
|
|
{
|
|
if ( !CheckValidate() )
|
|
return S_FALSE;
|
|
|
|
m_pPath->StartFigure();
|
|
//RELEASEOBJECT(m_pPath);
|
|
//m_pPath = new Gdiplus::GraphicsPath(FillModeWinding);
|
|
|
|
m_pPath->AddLine( fX, fY, fX, fY );
|
|
return S_OK;
|
|
}
|
|
inline STDMETHOD(LineTo)(float fX, float fY)
|
|
{
|
|
if ( !CheckValidate() )
|
|
return S_FALSE;
|
|
|
|
Gdiplus::PointF pointCur( 0, 0 );
|
|
CheckLastPoint( pointCur );
|
|
m_pPath->AddLine( pointCur.X, pointCur.Y, fX, fY );
|
|
|
|
return S_OK;
|
|
}
|
|
inline STDMETHOD(LinesTo)(SAFEARRAY** ppPoints)
|
|
{
|
|
if ( !CheckValidate() || ( NULL == ppPoints ) || ( NULL == *ppPoints ) )
|
|
return S_FALSE;
|
|
|
|
LONG lCount = (*ppPoints)->rgsabound[0].cElements;
|
|
lCount /= 2;
|
|
|
|
double* pPoints = (double*)((*ppPoints)->pvData);
|
|
|
|
CSimpleArray<Gdiplus::PointF> arPoints;
|
|
|
|
for (int nIndex = 0; nIndex < lCount; ++nIndex)
|
|
{
|
|
Gdiplus::PointF oPoint(*pPoints, *(pPoints + 1));
|
|
pPoints += 2;
|
|
arPoints.Add(oPoint);
|
|
}
|
|
|
|
if ( 1 < lCount )
|
|
{
|
|
m_pPath->AddLines(arPoints.m_aT, lCount);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
inline STDMETHOD(CurveTo)(float fX1, float fY1, float fX2, float fY2, float fX3, float fY3)
|
|
{
|
|
if ( !CheckValidate() )
|
|
return S_FALSE;
|
|
|
|
Gdiplus::PointF pointCur(0, 0);
|
|
|
|
CheckLastPoint(pointCur);
|
|
|
|
CSimpleArray<Gdiplus::PointF> arPoints;
|
|
|
|
arPoints.Add(pointCur);
|
|
|
|
pointCur.X = fX1; pointCur.Y = fY1;
|
|
arPoints.Add(pointCur);
|
|
pointCur.X = fX2; pointCur.Y = fY2;
|
|
arPoints.Add(pointCur);
|
|
pointCur.X = fX3; pointCur.Y = fY3;
|
|
arPoints.Add(pointCur);
|
|
|
|
//m_pPath->AddCurve(arPoints.m_aT, 4);
|
|
m_pPath->AddBeziers(arPoints.m_aT, 4);
|
|
|
|
return S_OK;
|
|
}
|
|
inline STDMETHOD(CurvesTo)(SAFEARRAY** ppPoints)
|
|
{
|
|
if ( !CheckValidate() )
|
|
return S_FALSE;
|
|
|
|
LONG lCount = (*ppPoints)->rgsabound[0].cElements;
|
|
lCount /= 2;
|
|
|
|
double* pPoints = (double*)((*ppPoints)->pvData);
|
|
|
|
CSimpleArray<Gdiplus::PointF> arPoints;
|
|
|
|
for (int nIndex = 0; nIndex < lCount; ++nIndex)
|
|
{
|
|
Gdiplus::PointF oPoint(*pPoints, *(pPoints + 1));
|
|
pPoints += 2;
|
|
arPoints.Add(oPoint);
|
|
}
|
|
|
|
int nSize = arPoints.GetSize();
|
|
if (1 < nSize)
|
|
{
|
|
//m_pPath->AddCurve(arPoints.m_aT, nSize);
|
|
m_pPath->AddBeziers(arPoints.m_aT, nSize);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
inline STDMETHOD(ArcTo)(float fX, float fY, float fWidth, float fHeight, float fStartAngle, float fSweepAngle)
|
|
{
|
|
if ( !CheckValidate() )
|
|
return S_FALSE;
|
|
|
|
m_pPath->AddArc(fX, fY, fWidth, fHeight, fStartAngle, fSweepAngle);
|
|
return S_OK;
|
|
}
|
|
inline STDMETHOD(Close)()
|
|
{
|
|
if ( !CheckValidate() )
|
|
return S_FALSE;
|
|
|
|
m_pPath->CloseFigure();
|
|
return S_OK;
|
|
}
|
|
inline STDMETHOD(End)()
|
|
{
|
|
if ( !CheckValidate() )
|
|
return S_FALSE;
|
|
|
|
m_pPath->Reset();
|
|
return S_OK;
|
|
}
|
|
|
|
inline STDMETHOD(Start)()
|
|
{
|
|
if ( !CheckValidate() )
|
|
return S_FALSE;
|
|
|
|
m_pPath->StartFigure();
|
|
return S_OK;
|
|
}
|
|
inline STDMETHOD(GetCurrentPoint)(float* fX, float* fY)
|
|
{
|
|
if ( !CheckValidate() )
|
|
return S_FALSE;
|
|
|
|
if ( ( NULL == fX ) || ( NULL == fY ) )
|
|
return S_FALSE;
|
|
|
|
Gdiplus::PointF oPoint(0, 0);
|
|
CheckLastPoint(oPoint);
|
|
|
|
*fX = oPoint.X;
|
|
*fY = oPoint.Y;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
private:
|
|
|
|
inline BOOL CheckValidate()
|
|
{
|
|
return ( NULL != m_pPath );
|
|
}
|
|
void CheckLastPoint(Gdiplus::PointF& pointCur)
|
|
{
|
|
if ( !CheckValidate() )
|
|
return;
|
|
|
|
int nCount = m_pPath->GetPointCount();
|
|
|
|
if ( 0 < nCount )
|
|
{
|
|
Gdiplus::PointF* pPoints = new Gdiplus::PointF[nCount];
|
|
m_pPath->GetPathPoints( pPoints, nCount );
|
|
|
|
pointCur.X = pPoints[nCount - 1].X;
|
|
pointCur.Y = pPoints[nCount - 1].Y;
|
|
|
|
delete []pPoints;
|
|
}
|
|
}
|
|
|
|
private:
|
|
|
|
Gdiplus::GraphicsPath *m_pPath;
|
|
};
|
|
|
|
static CString GetTempFileName()
|
|
{
|
|
CString sResult;
|
|
TCHAR ctTempPath [MAX_PATH];
|
|
DWORD dwTempPathLen = ::GetTempPath (MAX_PATH, ctTempPath);
|
|
if (0 != dwTempPathLen)
|
|
{
|
|
TCHAR ctTempFileName [MAX_PATH];
|
|
UINT nTempFileLen = ::GetTempFileName(ctTempPath, _T("asc"), 0, ctTempFileName);
|
|
if (0 != nTempFileLen)
|
|
{
|
|
sResult = ctTempFileName;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ATLTRACE2 ("GetTempPath() failed! (0x%x)\n", GetLastError());
|
|
}
|
|
return sResult;
|
|
}
|
|
static bool WriteFile (const CString& sTempLogo, const BYTE *cpLogo1, const size_t nSize = 0)
|
|
{
|
|
const size_t nCount = (0 == nSize) ? strlen ((const char*) cpLogo1) : nSize;
|
|
FILE *pFile = _tfopen (sTempLogo.GetString(), _T("w"));
|
|
const size_t nWritten = fwrite (cpLogo1, 1, nCount, pFile);
|
|
return (nWritten == nCount);
|
|
}
|
|
static bool DecodeBase64 (CStringA sBase64String, BYTE **aBuffer, DWORD *aBufferLen)
|
|
{
|
|
if (NULL == aBuffer || NULL == aBufferLen)
|
|
return false;
|
|
const int nSrcLength = sBase64String.GetLength();
|
|
const int nDecodedLength = Base64DecodeGetRequiredLength (nSrcLength);
|
|
*aBuffer = new BYTE [nDecodedLength];
|
|
|
|
if (NULL == *aBuffer)
|
|
return false;
|
|
|
|
int nTempLength = nDecodedLength;
|
|
LPCSTR pBase64Buffer = sBase64String.GetBuffer();
|
|
BOOL bDecoderResult = Base64Decode (pBase64Buffer, nSrcLength, *aBuffer, &nTempLength);
|
|
sBase64String.ReleaseBuffer();
|
|
*aBufferLen = nTempLength;
|
|
|
|
return TRUE == bDecoderResult;
|
|
}
|
|
|
|
struct ImageUtils
|
|
{
|
|
static inline IUnknown* LoadImage(CString sFilePath)
|
|
{
|
|
ImageStudio::IImageTransforms* pTransform = NULL;
|
|
if (FAILED(CoCreateInstance(__uuidof(ImageStudio::ImageTransforms), NULL, CLSCTX_INPROC_SERVER, __uuidof(ImageStudio::IImageTransforms), (void**)(&pTransform))))
|
|
return NULL;
|
|
|
|
if (!pTransform)
|
|
return NULL;
|
|
|
|
sFilePath.Replace( _T("\\\\"), _T("\\") );
|
|
|
|
CFileDownloader* loader = NULL;
|
|
if (CFileDownloader::IsNeedDownload(sFilePath))
|
|
{
|
|
loader = new CFileDownloader(sFilePath, TRUE);
|
|
if (loader)
|
|
{
|
|
loader->StartWork(1);
|
|
|
|
while(loader->IsRunned())
|
|
{
|
|
Sleep(10);
|
|
}
|
|
|
|
if (loader->IsFileDownloaded())
|
|
{
|
|
sFilePath = loader->GetFilePath();
|
|
}
|
|
}
|
|
}
|
|
|
|
CString sXml(L"<transforms><ImageFile-LoadImage sourcepath=\"");
|
|
sXml += sFilePath;
|
|
sXml += L"\"></ImageFile-LoadImage></transforms>";
|
|
|
|
BSTR bsXML = sXml.AllocSysString();
|
|
if (!pTransform->SetXml(bsXML))
|
|
{
|
|
SysFreeString(bsXML);
|
|
RELEASEINTERFACE(pTransform);
|
|
RELEASEOBJECT(loader);
|
|
return NULL;
|
|
}
|
|
|
|
SysFreeString(bsXML);
|
|
|
|
if (!pTransform->Transform())
|
|
{
|
|
RELEASEINTERFACE(pTransform);
|
|
RELEASEOBJECT(loader);
|
|
return NULL;
|
|
}
|
|
|
|
VARIANT vImage;
|
|
pTransform->GetResult(0, &vImage);
|
|
|
|
RELEASEINTERFACE(pTransform);
|
|
RELEASEOBJECT(loader);
|
|
|
|
if (VT_UNKNOWN != vImage.vt)
|
|
return NULL;
|
|
|
|
return vImage.punkVal;
|
|
}
|
|
};
|
|
|
|
// text utils
|
|
|
|
struct ParseUtils
|
|
{
|
|
static inline BOOL DoubleValues (const CString& src, CAtlArray<double>& numbers)
|
|
{
|
|
CString number = _T("");
|
|
int length = src.GetLength();
|
|
|
|
for (int i = 0; i < length; ++i)
|
|
{
|
|
if (L'-' == src [i])
|
|
{
|
|
if (i > 1)
|
|
{
|
|
if (L'e' == src [i - 1])
|
|
{
|
|
number.AppendChar(src[i]);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (number.GetLength())
|
|
numbers.Add(_tstof(number));
|
|
|
|
number = _T("");
|
|
}
|
|
|
|
if (isdigit(src[i]) || (src[i] == L'.') || (src[i] == L'-') || (src[i] == 'e'))
|
|
{
|
|
number.AppendChar(src[i]);
|
|
continue;
|
|
}
|
|
|
|
if (number.GetLength())
|
|
numbers.Add(_tstof(number));
|
|
|
|
number = _T("");
|
|
}
|
|
|
|
if (number.GetLength ())
|
|
numbers.Add(_tstof(number));
|
|
|
|
return (0 != numbers.GetCount());
|
|
}
|
|
};
|