Files
core/DesktopEditor/raster/Metafile/Emf/EmfPlayer.cpp

797 lines
20 KiB
C++

/*
* (c) Copyright Ascensio System SIA 2010-2023
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "EmfPlayer.h"
#include "EmfParser/CEmfParserBase.h"
#include <cmath>
namespace MetaFile
{
CEmfPlayer::CEmfPlayer(CEmfParserBase* pParser)
: m_pParser(pParser)
{
m_pDC = new CEmfDC(this);
if (!m_pDC)
{
if (NULL != m_pParser) m_pParser->SetError();
return;
}
InitStockObjects();
};
CEmfPlayer::~CEmfPlayer()
{
for (CEmfObjectMap::iterator oIterator = m_mObjects.begin(); oIterator != m_mObjects.end(); oIterator++)
{
CEmfObjectBase* pOldObject = oIterator->second;
delete pOldObject;
}
m_mObjects.clear();
for (EmfDCsMap::iterator oIterator = m_mDCs.begin(); oIterator != m_mDCs.end(); ++oIterator)
{
CEmfDC* pDC = oIterator->second;
RELEASEOBJECT(pDC);
}
m_mDCs.clear();
RELEASEOBJECT(m_pDC);
}
void CEmfPlayer::Clear()
{
for (CEmfObjectMap::iterator oIterator = m_mObjects.begin(); oIterator != m_mObjects.end(); oIterator++)
{
CEmfObjectBase* pOldObject = oIterator->second;
delete pOldObject;
}
m_mObjects.clear();
for (EmfDCsMap::iterator oIterator = m_mDCs.begin(); oIterator != m_mDCs.end(); ++oIterator)
{
CEmfDC* pDC = oIterator->second;
RELEASEOBJECT(pDC);
}
m_mDCs.clear();
RELEASEOBJECT(m_pDC);
m_pDC = new CEmfDC(this);
if (!m_pDC)
{
if (NULL != m_pParser) m_pParser->SetError();
return;
}
InitStockObjects();
SelectObject(0x80000007); // BLACK_PEN
SelectObject(0x80000000); // WHITE_BRUSH
}
void CEmfPlayer::SaveDC(int nIndex)
{
if (!m_pDC)
{
if (NULL != m_pParser) m_pParser->SetError();
return;
}
CEmfDC* pNewDC = m_pDC->Copy();
if (!pNewDC)
{
if (NULL != m_pParser) m_pParser->SetError();
return;
}
if (nIndex < 0)
{
if (m_mDCs.empty() || m_mDCs.begin()->first >= 0)
m_mDCs.insert(std::pair<int, CEmfDC*>(-1, pNewDC));
else
m_mDCs.insert(std::pair<int, CEmfDC*>(m_mDCs.begin()->first - 1, pNewDC));
}
else
{
EmfDCsMap::iterator oFound = m_mDCs.find(nIndex);
if (m_mDCs.end() != oFound)
{
delete oFound->second;
oFound->second = pNewDC;
}
else
m_mDCs.insert(std::pair<int, CEmfDC*>(nIndex, pNewDC));
}
}
void CEmfPlayer::RestoreDC(int nIndex)
{
if (nIndex < 0)
{
if (m_mDCs.empty() || m_mDCs.begin()->first > nIndex)
{
if (NULL != m_pParser) m_pParser->SetError();
return;
}
for (int nDeleteIndex = 0; nDeleteIndex > nIndex; --nDeleteIndex)
{
delete m_pDC;
m_pDC = m_mDCs.begin()->second;
m_mDCs.erase(m_mDCs.begin());
}
}
else
{
EmfDCsMap::iterator oFound = m_mDCs.find(nIndex);
if (m_mDCs.end() != oFound)
{
delete m_pDC;
m_pDC = oFound->second;
m_mDCs.erase(oFound);
}
else if (NULL != m_pParser)
m_pParser->SetError();
}
}
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)
DeleteObject(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;
default: 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: Сделать поиск по DC_BRUSH и DC_PEN
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->RemoveBrush((CEmfLogBrushEx*)pObject); break;
case EMF_OBJECT_FONT: m_pDC->RemoveFont((CEmfLogFont*)pObject); break;
case EMF_OBJECT_PEN: m_pDC->RemovePen((CEmfLogPen*)pObject); break;
default: break;
}
for (std::pair<int, CEmfDC*> oElement : m_mDCs)
{
CEmfDC* pDC = oElement.second;
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;
default: 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: Сделать шрифты
// DC_BRUSH и DC_PEN не надо выставлять
}
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->unBrushStyle = BS_NULL;
else
{
pBrush->unBrushStyle = BS_SOLID;
pBrush->oColor.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->unPenStyle = PS_NULL;
else
{
pPen->unPenStyle = PS_COSMETIC | PS_SOLID;
pPen->oColor.Set(r, g, b);
}
RegisterObject(ulIndex, (CEmfObjectBase*)pPen);
}
CEmfDC::CEmfDC(CEmfPlayer* pPlayer)
{
m_pPlayer = pPlayer;
m_ulMapMode = MM_TEXT;
m_pBrush = NULL;
m_pPen = NULL;
m_pFont = NULL;
m_oTransform.Init();
m_oInverseTransform.Init();
m_oTextColor.Set(0, 0, 0);
m_oFinalTransform.Init();
m_oBgColor.Set(255, 255, 255);
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;
m_oDefaultFont.oLogFontEx.oLogFont.ushFaceName[0] = 'A';
m_oDefaultFont.oLogFontEx.oLogFont.ushFaceName[1] = 'r';
m_oDefaultFont.oLogFontEx.oLogFont.ushFaceName[2] = 'i';
m_oDefaultFont.oLogFontEx.oLogFont.ushFaceName[3] = 'a';
m_oDefaultFont.oLogFontEx.oLogFont.ushFaceName[4] = 'l';
m_oDefaultFont.oLogFontEx.oLogFont.ushFaceName[5] = '\0';
m_oDefaultFont.oLogFontEx.oLogFont.uchCharSet = 1;
m_oDefaultFont.oLogFontEx.oLogFont.uchClipPrecision = 0;
m_oDefaultFont.oLogFontEx.oLogFont.nEscapement = 0;
m_oDefaultFont.oLogFontEx.oLogFont.nHeight = -18;
m_oDefaultFont.oLogFontEx.oLogFont.uchItalic = 0;
m_oDefaultFont.oLogFontEx.oLogFont.nOrientation = 0;
m_oDefaultFont.oLogFontEx.oLogFont.uchOutPrecision = 4;
m_oDefaultFont.oLogFontEx.oLogFont.uchPitchAndFamily = 2;
m_oDefaultFont.oLogFontEx.oLogFont.uchQuality = 0;
m_oDefaultFont.oLogFontEx.oLogFont.uchStrikeOut = 0;
m_oDefaultFont.oLogFontEx.oLogFont.uchUnderline = 0;
m_oDefaultFont.oLogFontEx.oLogFont.nWeight = 400;
m_oDefaultFont.oLogFontEx.oLogFont.nWidth = 0;
m_oDefaultFont.oDesignVector.pValues = NULL;
m_oDefaultFont.oDesignVector.unNumAxes = 0;
}
CEmfDC::~CEmfDC()
{
}
CEmfDC* CEmfDC::Copy()
{
CEmfDC* pNewDC = new CEmfDC(m_pPlayer);
if (!pNewDC)
return NULL;
pNewDC->m_oClip.Copy(m_oClip);
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_oFinalTransform.Copy(&m_oFinalTransform);
pNewDC->m_oFinalTransform2.Copy(&m_oFinalTransform2);
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_unArcDirection = m_unArcDirection;
return pNewDC;
}
CClip *CEmfDC::GetClip()
{
return &m_oClip;
}
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;
}
}
UpdateFinalTransform();
}
unsigned int CEmfDC::GetMapMode() const
{
return m_ulMapMode;
}
void CEmfDC::ResetTransform()
{
m_oTransform.Init();
UpdateFinalTransform();
}
const TEmfXForm& CEmfDC::GetTransform() const
{
return m_oTransform;
}
const TEmfXForm& CEmfDC::GetInverseTransform() const
{
return m_oInverseTransform;
}
const TEmfXForm& CEmfDC::GetFinalTransform(int iGraphicsMode) const
{
if (GM_COMPATIBLE == iGraphicsMode)
return m_oFinalTransform2;
return m_oFinalTransform;
}
void CEmfDC::MultiplyTransform(TEmfXForm& oForm, unsigned int ulMode)
{
m_oTransform.Multiply(oForm, ulMode);
// Обновляем обратную матрицу
TEmfXForm* pT = &m_oTransform;
const double dDet = pT->M11 * pT->M22 - pT->M12 * pT->M21;
if (Equals(0., 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;
}
else
{
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;
}
UpdateFinalTransform();
}
void CEmfDC::SetTextColor(const TRGBA& oColor)
{
m_oTextColor.Copy(oColor);
}
const TRGBA& CEmfDC::GetTextColor() const
{
return m_oTextColor;
}
void CEmfDC::SetBrush(IBrush *pBrush)
{
m_pBrush = pBrush;
}
void CEmfDC::RemoveBrush(IBrush* pBrush)
{
if (pBrush == m_pBrush)
m_pBrush = NULL;
}
const IBrush* CEmfDC::GetBrush() const
{
return m_pBrush;
}
void CEmfDC::SetFont(IFont* pFont)
{
m_pFont = pFont;
}
void CEmfDC::RemoveFont(IFont* pFont)
{
if (pFont == m_pFont)
m_pFont = NULL;
}
const IFont* CEmfDC::GetFont() const
{
return (NULL != m_pFont) ? m_pFont : &m_oDefaultFont;
}
void CEmfDC::SetTextAlign(unsigned int ulAlign)
{
m_ulTextAlign = ulAlign;
}
unsigned int CEmfDC::GetTextAlign() const
{
return m_ulTextAlign;
}
void CEmfDC::SetBgMode(unsigned int ulBgMode)
{
m_ulBgMode = ulBgMode;
}
unsigned int CEmfDC::GetBgMode() const
{
return m_ulBgMode;
}
void CEmfDC::SetBgColor(TRGBA& oColor)
{
m_oBgColor.Copy(oColor);
}
const TRGBA* CEmfDC::GetBgColor() const
{
return &m_oBgColor;
}
void CEmfDC::SetMiterLimit(unsigned int ulMiter)
{
m_ulMiterLimit = ulMiter;
}
unsigned int CEmfDC::GetMiterLimit() const
{
return m_ulMiterLimit;
}
void CEmfDC::SetFillMode(unsigned int ulFillMode)
{
m_ulFillMode = ulFillMode;
}
unsigned int CEmfDC::GetFillMode() const
{
return m_ulFillMode;
}
void CEmfDC::SetPen(IPen* pPen)
{
m_pPen = pPen;
}
void CEmfDC::RemovePen(IPen* pPen)
{
if (pPen == m_pPen)
m_pPen = NULL;
}
const IPen* CEmfDC::GetPen() const
{
return m_pPen;
}
void CEmfDC::SetStretchMode(unsigned int& oMode)
{
m_ulStretchMode = oMode;
}
unsigned int CEmfDC::GetStretchMode() const
{
return m_ulStretchMode;
}
double CEmfDC::GetPixelWidth() const
{
return m_dPixelWidth;
}
double CEmfDC::GetPixelHeight() const
{
return m_dPixelHeight;
}
void CEmfDC::SetPixelWidth(double dPixelW)
{
m_dPixelWidth = dPixelW;
}
void CEmfDC::SetPixelHeight(double dPixelH)
{
m_dPixelHeight = dPixelH;
}
void CEmfDC::SetWindowOrigin(const TPointL& oPoint)
{
m_oWindow.lX = oPoint.X;
m_oWindow.lY = oPoint.Y;
UpdatePixelMetrics();
UpdateFinalTransform();
}
void CEmfDC::SetWindowExtents(const TSizeL& oPoint)
{
m_oWindow.ulW = oPoint.X;
m_oWindow.ulH = oPoint.Y;
if (0 == m_oViewport.ulW || 0 == m_oViewport.ulH)
{
m_oViewport.ulW = oPoint.X;
m_oViewport.ulH = oPoint.Y;
}
if (MM_ISOTROPIC == m_ulMapMode)
FixIsotropic();
UpdatePixelMetrics();
UpdateFinalTransform();
}
void CEmfDC::ScaleWindow(const double& dXScale, const double& dYScale)
{
m_oWindow.ulW = (int)(m_oWindow.ulW * dXScale);
m_oWindow.ulH = (int)(m_oWindow.ulH * dYScale);
if (MM_ISOTROPIC == m_ulMapMode)
FixIsotropic();
UpdatePixelMetrics();
UpdateFinalTransform();
}
const TEmfWindow& CEmfDC::GetWindow() const
{
return m_oWindow;
}
void CEmfDC::SetViewportOrigin(const TPointL& oPoint)
{
m_oViewport.lX = oPoint.X;
m_oViewport.lY = oPoint.Y;
UpdatePixelMetrics();
UpdateFinalTransform();
}
void CEmfDC::SetViewportExtents(const TSizeL& oPoint)
{
m_oViewport.ulW = oPoint.X;
m_oViewport.ulH = oPoint.Y;
if (0 == m_oWindow.ulW || 0 == m_oWindow.ulH)
{
m_oWindow.ulW = oPoint.X;
m_oWindow.ulH = oPoint.Y;
}
if (MM_ISOTROPIC == m_ulMapMode)
FixIsotropic();
UpdatePixelMetrics();
UpdateFinalTransform();
}
void CEmfDC::ScaleViewport(const double& dXScale, const double& dYScale)
{
m_oViewport.ulW = (int)(m_oViewport.ulW * dXScale);
m_oViewport.ulH = (int)(m_oViewport.ulH * dYScale);
if (MM_ISOTROPIC == m_ulMapMode)
FixIsotropic();
UpdatePixelMetrics();
UpdateFinalTransform();
}
const TEmfWindow& CEmfDC::GetViewport() const
{
return m_oViewport;
}
bool CEmfDC::UpdatePixelMetrics()
{
unsigned int ulMapMode = m_ulMapMode;
if (1 >= m_oWindow.ulW || 1 >= m_oViewport.ulW)
return false;
if (MM_ISOTROPIC == ulMapMode)
{
double dPixel = (double)m_oViewport.ulW / (double)m_oWindow.ulW;
SetPixelHeight(dPixel);
SetPixelWidth(dPixel);
}
else if (MM_ANISOTROPIC == ulMapMode)
{
if (0 == m_oWindow.ulH || 0 == m_oViewport.ulH)
return false;
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::UpdateFinalTransform()
{
const TEmfWindow& oWindow{GetWindow()};
const TEmfWindow& oViewPort{GetViewport()};
double dM11 = ((oViewPort.ulW >= 0) ? 1. : -1.) * GetPixelWidth();
double dM22 = ((oViewPort.ulH >= 0) ? 1. : -1.) * GetPixelHeight();
TEmfXForm oWindowXForm(1, 0, 0, 1, -(oWindow.lX * dM11), -(oWindow.lY * dM22));
TEmfXForm oViewportXForm(dM11, 0, 0, dM22, oViewPort.lX, oViewPort.lY);
m_oFinalTransform.Init();
m_oFinalTransform.Multiply(m_oTransform, MWT_RIGHTMULTIPLY);
m_oFinalTransform.Multiply(oViewportXForm, MWT_RIGHTMULTIPLY);
m_oFinalTransform.Multiply(oWindowXForm, MWT_RIGHTMULTIPLY);
m_oFinalTransform2.Init();
// m_oFinalTransform2.Multiply(m_oTransform, MWT_RIGHTMULTIPLY);
m_oFinalTransform2.Multiply(oViewportXForm, MWT_RIGHTMULTIPLY);
m_oFinalTransform2.Multiply(oWindowXForm, MWT_RIGHTMULTIPLY);
}
void CEmfDC::FixIsotropic()
{
double dXDim = std::fabs((double)m_oViewport.ulW / m_oWindow.ulW);
double dYDim = std::fabs((double)m_oViewport.ulH / m_oWindow.ulH);
if (dXDim > dYDim)
{
int nMinCx = (m_oViewport.ulW >= 0) ? 1 : -1;
m_oViewport.ulW = std::floor(m_oViewport.ulW * dYDim / dXDim + 0.5);
if (!m_oViewport.ulW) m_oViewport.ulW = nMinCx;
}
else
{
int nMinCy = (m_oViewport.ulH >= 0) ? 1 : -1;
m_oViewport.ulH = std::floor(m_oViewport.ulH * dXDim / dYDim + 0.5);
if (!m_oViewport.ulH) m_oViewport.ulH = nMinCy;
}
}
void CEmfDC::SetRop2Mode(unsigned int nMode)
{
m_ulRop2Mode = nMode;
}
unsigned int CEmfDC::GetRop2Mode() const
{
return m_ulRop2Mode;
}
void CEmfDC::SetPalette(CEmfLogPalette* pPalette)
{
m_pPalette = pPalette;
}
void CEmfDC::RemovePalette(CEmfLogPalette* pPalette)
{
if (m_pPalette == pPalette)
m_pPalette = NULL;
}
const CEmfLogPalette* CEmfDC::GetPalette() const
{
return m_pPalette;
}
void CEmfDC::SetCurPos(const TPointL& oPoint)
{
SetCurPos(oPoint.X, oPoint.Y);
}
void CEmfDC::SetCurPos(int lX, int lY)
{
m_oCurPos.X = lX;
m_oCurPos.Y = lY;
}
const TPointL& CEmfDC::GetCurPos() const
{
return m_oCurPos;
}
void CEmfDC::SetArcDirection(unsigned int unDirection)
{
m_unArcDirection = unDirection;
}
unsigned int CEmfDC::GetArcDirection() const
{
return m_unArcDirection;
}
}