mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 14:00:32 +08:00
583 lines
14 KiB
C++
583 lines
14 KiB
C++
#include "EmfPlayer.h"
|
||
#include "EmfFile.h"
|
||
|
||
namespace MetaFile
|
||
{
|
||
CEmfPlayer::CEmfPlayer(CEmfFile* pFile)
|
||
{
|
||
CEmfDC* pDC = new CEmfDC();
|
||
if (!pDC)
|
||
{
|
||
pFile->SetError();
|
||
return;
|
||
}
|
||
|
||
m_pEmfFile = pFile;
|
||
m_pDC = pDC;
|
||
m_vDCStack.push_back(pDC);
|
||
|
||
InitStockObjects();
|
||
};
|
||
CEmfPlayer::~CEmfPlayer()
|
||
{
|
||
for (int nIndex = 0; nIndex < m_vDCStack.size(); nIndex++)
|
||
{
|
||
CEmfDC* pDC = m_vDCStack.at(nIndex);
|
||
delete pDC;
|
||
}
|
||
m_vDCStack.clear();
|
||
|
||
for (CEmfObjectMap::iterator oIterator = m_mObjects.begin(); oIterator != m_mObjects.end(); oIterator++)
|
||
{
|
||
CEmfObjectBase* pOldObject = oIterator->second;
|
||
delete pOldObject;
|
||
}
|
||
m_mObjects.clear();
|
||
}
|
||
void CEmfPlayer::Clear()
|
||
{
|
||
for (int nIndex = 0; nIndex < m_vDCStack.size(); nIndex++)
|
||
{
|
||
CEmfDC* pDC = m_vDCStack.at(nIndex);
|
||
delete pDC;
|
||
}
|
||
m_vDCStack.clear();
|
||
|
||
for (CEmfObjectMap::iterator oIterator = m_mObjects.begin(); oIterator != m_mObjects.end(); oIterator++)
|
||
{
|
||
CEmfObjectBase* pOldObject = oIterator->second;
|
||
delete pOldObject;
|
||
}
|
||
m_mObjects.clear();
|
||
|
||
CEmfDC* pDC = new CEmfDC();
|
||
if (!pDC)
|
||
{
|
||
m_pEmfFile->SetError();
|
||
return;
|
||
}
|
||
|
||
m_pDC = pDC;
|
||
m_vDCStack.push_back(pDC);
|
||
InitStockObjects();
|
||
|
||
SelectObject(0x80000007); // BLACK_PEN
|
||
SelectObject(0x80000000); // WHITE_BRUSH
|
||
}
|
||
CEmfDC* CEmfPlayer::SaveDC()
|
||
{
|
||
if (!m_pDC)
|
||
{
|
||
m_pEmfFile->SetError();
|
||
return NULL;
|
||
}
|
||
|
||
CEmfDC* pNewDC = m_pDC->Copy();
|
||
if (!pNewDC)
|
||
{
|
||
m_pEmfFile->SetError();
|
||
return NULL;
|
||
}
|
||
|
||
m_vDCStack.push_back(pNewDC);
|
||
m_pDC = pNewDC;
|
||
return pNewDC;
|
||
}
|
||
CEmfDC* CEmfPlayer::RestoreDC()
|
||
{
|
||
if (m_vDCStack.size() <= 1)
|
||
{
|
||
m_pEmfFile->SetError();
|
||
return m_pDC;
|
||
}
|
||
|
||
CEmfDC* pDC = m_vDCStack.at(m_vDCStack.size() - 1);
|
||
m_vDCStack.pop_back();
|
||
delete pDC;
|
||
|
||
pDC = m_vDCStack.at(m_vDCStack.size() - 1);
|
||
m_pDC = pDC;
|
||
return m_pDC;
|
||
}
|
||
CEmfDC* CEmfPlayer::GetDC()
|
||
{
|
||
return m_pDC;
|
||
}
|
||
void CEmfPlayer::RegisterObject(unsigned int ulIndex, CEmfObjectBase* pObject)
|
||
{
|
||
CEmfObjectMap::const_iterator oPos = m_mObjects.find(ulIndex);
|
||
if (m_mObjects.end() != oPos)
|
||
{
|
||
CEmfObjectBase* pOldObject = oPos->second;
|
||
delete pOldObject;
|
||
m_mObjects.erase(ulIndex);
|
||
}
|
||
|
||
m_mObjects.insert(std::pair<unsigned int, CEmfObjectBase*>(ulIndex, pObject));
|
||
}
|
||
void CEmfPlayer::SelectObject(unsigned int ulIndex)
|
||
{
|
||
CEmfObjectMap::const_iterator oPos = m_mObjects.find(ulIndex);
|
||
if (m_mObjects.end() != oPos)
|
||
{
|
||
CEmfObjectBase* pObject = oPos->second;
|
||
|
||
switch (pObject->GetType())
|
||
{
|
||
case EMF_OBJECT_BRUSH: m_pDC->SetBrush((CEmfLogBrushEx*)pObject); break;
|
||
case EMF_OBJECT_FONT: m_pDC->SetFont((CEmfLogFont*)pObject); break;
|
||
case EMF_OBJECT_PEN: m_pDC->SetPen((CEmfLogPen*)pObject); break;
|
||
}
|
||
}
|
||
}
|
||
void CEmfPlayer::SelectPalette(unsigned int ulIndex)
|
||
{
|
||
// DEFAULT_PALETTE
|
||
if (ulIndex == 0x8000000F)
|
||
m_pDC->SetPalette(NULL);
|
||
|
||
CEmfObjectMap::const_iterator oPos = m_mObjects.find(ulIndex);
|
||
if (m_mObjects.end() != oPos)
|
||
{
|
||
CEmfObjectBase* pObject = oPos->second;
|
||
if (EMF_OBJECT_PALETTE == pObject->GetType())
|
||
m_pDC->SetPalette((CEmfLogPalette*)pObject);
|
||
}
|
||
}
|
||
void CEmfPlayer::DeleteObject(unsigned int ulIndex)
|
||
{
|
||
// TODO: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><> DC_BRUSH <20> DC_PEN
|
||
|
||
CEmfObjectMap::const_iterator oPos = m_mObjects.find(ulIndex);
|
||
if (m_mObjects.end() != oPos)
|
||
{
|
||
CEmfObjectBase* pObject = oPos->second;
|
||
|
||
for (int nIndex = 0; nIndex < m_vDCStack.size(); nIndex++)
|
||
{
|
||
CEmfDC* pDC = m_vDCStack.at(nIndex);
|
||
|
||
switch (pObject->GetType())
|
||
{
|
||
case EMF_OBJECT_BRUSH: pDC->RemoveBrush((CEmfLogBrushEx*)pObject); break;
|
||
case EMF_OBJECT_FONT: pDC->RemoveFont((CEmfLogFont*)pObject); break;
|
||
case EMF_OBJECT_PEN: pDC->RemovePen((CEmfLogPen*)pObject); break;
|
||
}
|
||
}
|
||
|
||
delete pObject;
|
||
m_mObjects.erase(ulIndex);
|
||
}
|
||
}
|
||
void CEmfPlayer::InitStockObjects()
|
||
{
|
||
InitStockBrush(false, 0xff, 0xff, 0xff, 0x80000000);
|
||
InitStockBrush(false, 0xc0, 0xc0, 0xc0, 0x80000001);
|
||
InitStockBrush(false, 0x80, 0x80, 0x80, 0x80000002);
|
||
InitStockBrush(false, 0x40, 0x40, 0x40, 0x80000003);
|
||
InitStockBrush(false, 0x00, 0x00, 0x00, 0x80000004);
|
||
InitStockBrush(true, 0x00, 0x00, 0x00, 0x80000005);
|
||
InitStockPen(false, 0xff, 0xff, 0xff, 0x80000006);
|
||
InitStockPen(false, 0x00, 0x00, 0x00, 0x80000007);
|
||
InitStockPen(true, 0x00, 0x00, 0x00, 0x80000008);
|
||
// TODO: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
// DC_BRUSH <20> DC_PEN <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
}
|
||
void CEmfPlayer::InitStockBrush(bool bNull, unsigned char r, unsigned char g, unsigned char b, unsigned int ulIndex)
|
||
{
|
||
CEmfLogBrushEx* pBrush = new CEmfLogBrushEx();
|
||
if (!pBrush)
|
||
return;
|
||
|
||
if (bNull)
|
||
pBrush->BrushStyle = BS_NULL;
|
||
else
|
||
{
|
||
pBrush->BrushStyle = BS_SOLID;
|
||
pBrush->Color.Set(r, g, b);
|
||
}
|
||
|
||
RegisterObject(ulIndex, (CEmfObjectBase*)pBrush);
|
||
}
|
||
void CEmfPlayer::InitStockPen(bool bNull, unsigned char r, unsigned char g, unsigned char b, unsigned int ulIndex)
|
||
{
|
||
CEmfLogPen* pPen = new CEmfLogPen();
|
||
if (!pPen)
|
||
return;
|
||
|
||
if (bNull)
|
||
pPen->PenStyle = PS_NULL;
|
||
else
|
||
{
|
||
pPen->PenStyle = PS_COSMETIC | PS_SOLID;
|
||
pPen->Color.Set(r, g, b);
|
||
}
|
||
|
||
RegisterObject(ulIndex, (CEmfObjectBase*)pPen);
|
||
}
|
||
|
||
CEmfDC::CEmfDC()
|
||
{
|
||
m_ulMapMode = MM_TEXT;
|
||
m_pBrush = NULL;
|
||
m_pPen = NULL;
|
||
m_pFont = NULL;
|
||
m_oTransform.Init();
|
||
m_oInverseTransform.Init();
|
||
m_oTextColor.Init();
|
||
m_oBgColor.Init();
|
||
m_ulTextAlign = TA_TOP | TA_LEFT | TA_NOUPDATECP;
|
||
m_ulBgMode = TRANSPARENT;
|
||
m_ulMiterLimit = 0;
|
||
m_ulFillMode = WINDING;
|
||
m_ulStretchMode = 0;
|
||
m_oWindow.Init();
|
||
m_oViewport.Init();
|
||
m_dPixelHeight = 1;
|
||
m_dPixelWidth = 1;
|
||
m_oCurPos.x = 0;
|
||
m_oCurPos.y = 0;
|
||
m_unArcDirection = AD_COUNTERCLOCKWISE;
|
||
}
|
||
CEmfDC::~CEmfDC()
|
||
{
|
||
}
|
||
CEmfDC* CEmfDC::Copy()
|
||
{
|
||
CEmfDC* pNewDC = new CEmfDC();
|
||
if (!pNewDC)
|
||
return NULL;
|
||
|
||
pNewDC->m_ulMapMode = m_ulMapMode;
|
||
pNewDC->m_pBrush = m_pBrush;
|
||
pNewDC->m_pPen = m_pPen;
|
||
pNewDC->m_pFont = m_pFont;
|
||
pNewDC->m_pPalette = m_pPalette;
|
||
pNewDC->m_oTransform.Copy(&m_oTransform);
|
||
pNewDC->m_oInverseTransform.Copy(&m_oInverseTransform);
|
||
pNewDC->m_oTextColor.Copy(&m_oTextColor);
|
||
pNewDC->m_oBgColor.Copy(&m_oBgColor);
|
||
pNewDC->m_ulTextAlign = m_ulTextAlign;
|
||
pNewDC->m_ulBgMode = m_ulBgMode;
|
||
pNewDC->m_ulMiterLimit = m_ulMiterLimit;
|
||
pNewDC->m_ulFillMode = m_ulFillMode;
|
||
pNewDC->m_ulStretchMode = m_ulStretchMode;
|
||
pNewDC->m_ulRop2Mode = m_ulRop2Mode;
|
||
pNewDC->m_dPixelHeight = m_dPixelHeight;
|
||
pNewDC->m_dPixelWidth = m_dPixelWidth;
|
||
pNewDC->m_oWindow.Copy(&m_oWindow);
|
||
pNewDC->m_oViewport.Copy(&m_oViewport);
|
||
pNewDC->m_oCurPos = m_oCurPos;
|
||
pNewDC->m_oClip = m_oClip;
|
||
pNewDC->m_unArcDirection = m_unArcDirection;
|
||
|
||
return pNewDC;
|
||
}
|
||
void CEmfDC::SetMapMode(unsigned int ulMapMode)
|
||
{
|
||
m_ulMapMode = ulMapMode;
|
||
|
||
switch (ulMapMode)
|
||
{
|
||
case MM_TEXT: // 1 unit = 1pt
|
||
{
|
||
SetPixelWidth(1);
|
||
SetPixelHeight(1);
|
||
break;
|
||
}
|
||
case MM_LOMETRIC: // 1 unit = 0.1mm
|
||
{
|
||
double dPixel = 0.1 * 72 / 25.4;
|
||
SetPixelWidth(dPixel);
|
||
SetPixelHeight(dPixel);
|
||
break;
|
||
}
|
||
case MM_HIMETRIC: // 1 unit = 0.01mm
|
||
{
|
||
double dPixel = 0.01 * 72 / 25.4;
|
||
SetPixelWidth(dPixel);
|
||
SetPixelHeight(dPixel);
|
||
break;
|
||
}
|
||
case MM_LOENGLISH: // 1 unit = 0.01 inch
|
||
{
|
||
double dPixel = 0.01 * 72;
|
||
SetPixelWidth(dPixel);
|
||
SetPixelHeight(dPixel);
|
||
break;
|
||
}
|
||
case MM_HIENGLISH: // 1 unit = 0.001 inch
|
||
{
|
||
double dPixel = 0.001 * 72;
|
||
SetPixelWidth(dPixel);
|
||
SetPixelHeight(dPixel);
|
||
break;
|
||
}
|
||
case MM_TWIPS: // 1 unit = 1/1440 inch
|
||
{
|
||
SetPixelWidth(0.05);
|
||
SetPixelHeight(0.05);
|
||
break;
|
||
}
|
||
case MM_ISOTROPIC:
|
||
case MM_ANISOTROPIC:
|
||
{
|
||
UpdatePixelMetrics();
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
unsigned int CEmfDC::GetMapMode()
|
||
{
|
||
return m_ulMapMode;
|
||
}
|
||
TEmfXForm* CEmfDC::GetTransform()
|
||
{
|
||
return &m_oTransform;
|
||
}
|
||
TEmfXForm* CEmfDC::GetInverseTransform()
|
||
{
|
||
return &m_oInverseTransform;
|
||
}
|
||
void CEmfDC::MultiplyTransform(TEmfXForm& oForm, unsigned int ulMode)
|
||
{
|
||
m_oTransform.Multiply(oForm, ulMode);
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
TEmfXForm* pT = &m_oTransform;
|
||
double dDet = pT->M11 * pT->M22 - pT->M12 * pT->M21;
|
||
if (dDet < 0.0001 && dDet > 0.0001)
|
||
{
|
||
m_oInverseTransform.M11 = 1;
|
||
m_oInverseTransform.M12 = 0;
|
||
m_oInverseTransform.M21 = 0;
|
||
m_oInverseTransform.M22 = 1;
|
||
m_oInverseTransform.Dx = 0;
|
||
m_oInverseTransform.Dy = 0;
|
||
}
|
||
|
||
m_oInverseTransform.M11 = pT->M22 / dDet;
|
||
m_oInverseTransform.M12 = -pT->M12 / dDet;
|
||
m_oInverseTransform.M21 = -pT->M21 / dDet;
|
||
m_oInverseTransform.M22 = pT->M22 / dDet;
|
||
m_oInverseTransform.Dx = pT->Dy * pT->M21 / dDet - pT->Dx * pT->M22 / dDet;
|
||
m_oInverseTransform.Dy = pT->Dx * pT->M12 / dDet - pT->Dy * pT->M11 / dDet;
|
||
}
|
||
void CEmfDC::SetTextColor(TEmfColor& oColor)
|
||
{
|
||
m_oTextColor.Copy(&oColor);
|
||
}
|
||
TEmfColor& CEmfDC::GetTextColor()
|
||
{
|
||
return m_oTextColor;
|
||
}
|
||
void CEmfDC::SetBrush(CEmfLogBrushEx* pBrush)
|
||
{
|
||
m_pBrush = pBrush;
|
||
}
|
||
void CEmfDC::RemoveBrush(CEmfLogBrushEx* pBrush)
|
||
{
|
||
if (pBrush == m_pBrush)
|
||
m_pBrush = NULL;
|
||
}
|
||
CEmfLogBrushEx* CEmfDC::GetBrush()
|
||
{
|
||
return m_pBrush;
|
||
}
|
||
void CEmfDC::SetFont(CEmfLogFont* pFont)
|
||
{
|
||
m_pFont = pFont;
|
||
}
|
||
void CEmfDC::RemoveFont(CEmfLogFont* pFont)
|
||
{
|
||
if (pFont == m_pFont)
|
||
m_pFont = NULL;
|
||
}
|
||
CEmfLogFont* CEmfDC::GetFont()
|
||
{
|
||
return m_pFont;
|
||
}
|
||
void CEmfDC::SetTextAlign(unsigned int ulAlign)
|
||
{
|
||
m_ulTextAlign = ulAlign;
|
||
}
|
||
unsigned int CEmfDC::GetTextAlign()
|
||
{
|
||
return m_ulTextAlign;
|
||
}
|
||
void CEmfDC::SetBgMode(unsigned int ulBgMode)
|
||
{
|
||
m_ulBgMode = ulBgMode;
|
||
}
|
||
unsigned int CEmfDC::GetBgMode()
|
||
{
|
||
return m_ulBgMode;
|
||
}
|
||
void CEmfDC::SetBgColor(TEmfColor& oColor)
|
||
{
|
||
m_oBgColor.Copy(&oColor);
|
||
}
|
||
TEmfColor& CEmfDC::GetBgColor()
|
||
{
|
||
return m_oBgColor;
|
||
}
|
||
void CEmfDC::SetMiterLimit(unsigned int ulMiter)
|
||
{
|
||
m_ulMiterLimit = ulMiter;
|
||
}
|
||
unsigned int CEmfDC::GetMiterLimit()
|
||
{
|
||
return m_ulMiterLimit;
|
||
}
|
||
void CEmfDC::SetFillMode(unsigned int ulFillMode)
|
||
{
|
||
m_ulFillMode = ulFillMode;
|
||
}
|
||
unsigned int CEmfDC::GetFillMode()
|
||
{
|
||
return m_ulFillMode;
|
||
}
|
||
void CEmfDC::SetPen(CEmfLogPen* pPen)
|
||
{
|
||
m_pPen = pPen;
|
||
}
|
||
void CEmfDC::RemovePen(CEmfLogPen* pPen)
|
||
{
|
||
if (pPen == m_pPen)
|
||
m_pPen = NULL;
|
||
}
|
||
CEmfLogPen* CEmfDC::GetPen()
|
||
{
|
||
return m_pPen;
|
||
}
|
||
void CEmfDC::SetStretchMode(unsigned int& oMode)
|
||
{
|
||
m_ulStretchMode = oMode;
|
||
}
|
||
unsigned int CEmfDC::GetStretchMode()
|
||
{
|
||
return m_ulStretchMode;
|
||
}
|
||
double CEmfDC::GetPixelWidth()
|
||
{
|
||
return m_dPixelWidth;
|
||
}
|
||
double CEmfDC::GetPixelHeight()
|
||
{
|
||
return m_dPixelHeight;
|
||
}
|
||
void CEmfDC::SetPixelWidth(double dPixelW)
|
||
{
|
||
m_dPixelWidth = dPixelW;
|
||
}
|
||
void CEmfDC::SetPixelHeight(double dPixelH)
|
||
{
|
||
m_dPixelHeight = dPixelH;
|
||
}
|
||
void CEmfDC::SetWindowOrigin(TEmfPointL& oPoint)
|
||
{
|
||
m_oWindow.lX = oPoint.x;
|
||
m_oWindow.lY = oPoint.y;
|
||
UpdatePixelMetrics();
|
||
}
|
||
void CEmfDC::SetWindowExtents(TEmfSizeL& oPoint)
|
||
{
|
||
m_oWindow.ulW = oPoint.cx;
|
||
m_oWindow.ulH = oPoint.cy;
|
||
UpdatePixelMetrics();
|
||
}
|
||
TEmfWindow* CEmfDC::GetWindow()
|
||
{
|
||
return &m_oWindow;
|
||
}
|
||
void CEmfDC::SetViewportOrigin(TEmfPointL& oPoint)
|
||
{
|
||
m_oViewport.lX = oPoint.x;
|
||
m_oViewport.lY = oPoint.y;
|
||
UpdatePixelMetrics();
|
||
}
|
||
void CEmfDC::SetViewportExtents(TEmfSizeL& oPoint)
|
||
{
|
||
m_oViewport.ulW = oPoint.cx;
|
||
m_oViewport.ulH = oPoint.cy;
|
||
UpdatePixelMetrics();
|
||
}
|
||
TEmfWindow* CEmfDC::GetViewport()
|
||
{
|
||
return &m_oViewport;
|
||
}
|
||
bool CEmfDC::UpdatePixelMetrics()
|
||
{
|
||
unsigned int ulMapMode = m_ulMapMode;
|
||
if (MM_ISOTROPIC == ulMapMode)
|
||
{
|
||
if (0 == m_oWindow.ulW || 0 == m_oViewport.ulW)
|
||
return false;
|
||
|
||
double dPixel = (double)m_oViewport.ulW / (double)m_oWindow.ulW;
|
||
SetPixelHeight(dPixel);
|
||
SetPixelWidth(dPixel);
|
||
}
|
||
else if (MM_ANISOTROPIC == ulMapMode)
|
||
{
|
||
double dPixelX = (double)m_oViewport.ulW / (double)m_oWindow.ulW;
|
||
double dPixelY = (double)m_oViewport.ulH / (double)m_oWindow.ulH;
|
||
|
||
SetPixelWidth(dPixelX);
|
||
SetPixelHeight(dPixelY);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
void CEmfDC::SetRop2Mode(unsigned int& nMode)
|
||
{
|
||
m_ulRop2Mode = nMode;
|
||
}
|
||
unsigned int CEmfDC::GetRop2Mode()
|
||
{
|
||
return m_ulRop2Mode;
|
||
}
|
||
void CEmfDC::SetPalette(CEmfLogPalette* pPalette)
|
||
{
|
||
m_pPalette = pPalette;
|
||
}
|
||
void CEmfDC::RemovePalette(CEmfLogPalette* pPalette)
|
||
{
|
||
if (m_pPalette == pPalette)
|
||
m_pPalette = NULL;
|
||
}
|
||
CEmfLogPalette* CEmfDC::GetPalette()
|
||
{
|
||
return m_pPalette;
|
||
}
|
||
void CEmfDC::SetCurPos(TEmfPointL& oPoint)
|
||
{
|
||
SetCurPos(oPoint.x, oPoint.y);
|
||
}
|
||
void CEmfDC::SetCurPos(int lX, int lY)
|
||
{
|
||
m_oCurPos.x = lX;
|
||
m_oCurPos.y = lY;
|
||
}
|
||
TEmfPointL& CEmfDC::GetCurPos()
|
||
{
|
||
return m_oCurPos;
|
||
}
|
||
CEmfClip* CEmfDC::GetClip()
|
||
{
|
||
return &m_oClip;
|
||
}
|
||
void CEmfDC::ClipToPath(CEmfPath* pPath, unsigned int unMode)
|
||
{
|
||
m_oClip.SetPath(pPath, unMode);
|
||
}
|
||
void CEmfDC::SetArcDirection(unsigned int unDirection)
|
||
{
|
||
m_unArcDirection = unDirection;
|
||
}
|
||
unsigned int CEmfDC::GetArcDirection()
|
||
{
|
||
return m_unArcDirection;
|
||
}
|
||
} |