Files
Yajbir Singh f1b860b25c
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

1549 lines
41 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 "GraphicsRenderer.h"
#include <algorithm>
#ifndef GRAPHICS_DISABLE_METAFILE
#include "../raster/Metafile/MetaFile.h"
#endif
#if 0
static void LOGGING(char* buffer, ...)
{
FILE* f = fopen("path_to_log.txt", "a+");
va_list args;
va_start(args, buffer);
vfprintf(f, buffer, args);
fprintf(f, "\n");
fclose(f);
va_end(args);
}
#endif
////////////////////////////////////////////////////////////////////////////////
Aggplus::CBrush* CGraphicsRenderer::CreateBrush(NSStructures::CBrush* pBrush)
{
if (NULL == pBrush)
return NULL;
bool bIsSwappedRGB = false;
if (m_pRenderer && m_pRenderer->m_bSwapRGB)
bIsSwappedRGB = true;
LONG Type = pBrush->Type;
if ((0 == Type) || (c_BrushTypeSolid == Type))
{
Aggplus::CColor oColor((BYTE)(pBrush->Alpha1 * m_dGlobalAlpha), pBrush->Color1, bIsSwappedRGB);
if (m_pRenderer && m_pRenderer->m_bIsDarkMode)
oColor.ConvertToDarkMode(bIsSwappedRGB);
Aggplus::CBrushSolid* pNew = new Aggplus::CBrushSolid(oColor);
return pNew;
}
else if ((c_BrushTypeHorizontal == Type) ||
(c_BrushTypeVertical == Type) ||
(c_BrushTypeDiagonal1 == Type) ||
(c_BrushTypeDiagonal2 == Type) ||
(c_BrushTypeCenter == Type) ||
(c_BrushTypePathGradient1 == Type) ||
(c_BrushTypePathGradient2 == Type) ||
(c_BrushTypeCylinderHor == Type) ||
(c_BrushTypeCylinderVer == Type) ||
(c_BrushTypePathRadialGradient == Type) ||
(c_BrushTypePathNewLinearGradient == Type) ||
(c_BrushTypePathConicalGradient == Type) ||
(c_BrushTypePathDiamondGradient == Type) ||
(c_BrushTypeMyTestGradient == Type) ||
(c_BrushTypeTriagnleMeshGradient == Type) ||
(c_BrushTypeCurveGradient == Type) ||
(c_BrushTypeTensorCurveGradient == Type))
{
Aggplus::CColor o1((BYTE)(pBrush->Alpha1 * m_dGlobalAlpha), pBrush->Color1, bIsSwappedRGB);
Aggplus::CColor o2((BYTE)(pBrush->Alpha2 * m_dGlobalAlpha), pBrush->Color2, bIsSwappedRGB);
Aggplus::CBrushLinearGradient* pNew = new Aggplus::CBrushLinearGradient( Aggplus::RectF(0.0f, 0.0f, 1.0f, 1.0f), o1, o2, (float)pBrush->LinearAngle, TRUE );
if( pNew )
{
pNew->SetRelativeCoords( TRUE );
pNew->m_oGradientInfo = pBrush->m_oGradientInfo;
int nCountSubColors = pBrush->m_arrSubColors.size();
if( nCountSubColors > 0 )
{
Aggplus::CColor* pColors = new Aggplus::CColor[nCountSubColors];
float* pBlends = new float[nCountSubColors];
if( pColors && pBlends )
{
for( int i = 0; i < nCountSubColors; i++ )
{
DWORD dwColor = (DWORD)pBrush->m_arrSubColors[i].color;
BYTE a = (dwColor >> 24) & 0xFF;
BYTE b = (dwColor >> 16) & 0xFF;
BYTE g = (dwColor >> 8) & 0xFF;
BYTE r = (dwColor) & 0xFF;
if (bIsSwappedRGB)
{
BYTE tmp = r;
r = b;
b = tmp;
}
pColors[i] = Aggplus::CColor((BYTE)(a * m_dGlobalAlpha), b, g, r);
pBlends[i] = (float)(pBrush->m_arrSubColors[i].position / 65536.0);
}
pNew->SetInterpolationColors( pColors, pBlends, nCountSubColors );
}
delete [] pColors;
delete [] pBlends;
}
pNew->SetBounds(pBrush->Bounds);
}
if(!pNew)
return NULL;
switch (Type)
{
case c_BrushTypePathGradient2:
pNew->m_bType = Aggplus::BrushTypePathGradient;
break;
case c_BrushTypeMyTestGradient:
pNew->m_bType = Aggplus::BrushTypeMyTestGradient;
break;
case c_BrushTypePathRadialGradient:
pNew->m_bType = Aggplus::BrushTypeRadialGradient;
break;
case c_BrushTypePathNewLinearGradient:
pNew->m_bType = Aggplus::BrushTypeNewLinearGradient;
break;
case c_BrushTypePathConicalGradient:
pNew->m_bType = Aggplus::BrushTypeConicalGradient;
break;
case c_BrushTypePathDiamondGradient:
pNew->m_bType = Aggplus::BrushTypeDiamondGradient;
break;
case c_BrushTypeTensorCurveGradient:
pNew->m_bType = Aggplus::BrushTypeTensorCurveGradient;
break;
case c_BrushTypeCurveGradient:
pNew->m_bType = Aggplus::BrushTypeCurveGradient;
break;
case c_BrushTypeTriagnleMeshGradient:
pNew->m_bType = Aggplus::BrushTypeTriagnleMeshGradient;
break;
default:
break;
}
return pNew;
}
else if (c_BrushTypeHatch1 == Type)
{
Aggplus::CColor o1((BYTE)(pBrush->Alpha1 * m_dGlobalAlpha), pBrush->Color1, bIsSwappedRGB);
Aggplus::CColor o2((BYTE)(pBrush->Alpha2 * m_dGlobalAlpha), pBrush->Color2, bIsSwappedRGB);
Aggplus::CBrushHatch* pNew = new Aggplus::CBrushHatch();
pNew->m_dwColor1 = o1;
pNew->m_dwColor2 = o2;
pNew->m_name = pBrush->TexturePath;
pNew->Bounds = pBrush->Bounds;
return pNew;
}
else
{
Aggplus::CBrushTexture* pNew;
if (NULL != pBrush->Image)
pNew = new Aggplus::CBrushTexture(pBrush->Image, Aggplus::WrapModeClamp);
else
pNew = new Aggplus::CBrushTexture(pBrush->TexturePath, Aggplus::WrapModeClamp);
pNew->SetTransform(&m_oBrush.Transform);
return pNew;
}
}
CGraphicsRenderer::CGraphicsRenderer() : NSGraphics::IGraphicsRenderer()
{
m_pRenderer = NULL;
m_pPath = NULL;
m_dWidth = 210;
m_dHeight = 190;
m_dPixelsWidth = 720;
m_dPixelsHeight = 576;
m_lCurrentCommandType = 0;
m_lCurrentClipMode = 0;
m_bIsSetupClip = FALSE;
m_pFontManager = NULL;
m_oInstalledFont.Name = L"";
m_pPixels = NULL;
m_pDIB = NULL;
m_pCache = NULL;
m_dGlobalAlpha = 1.0;
m_bGlobalAlphaEnabled = false;
m_dGammaStroke = -1;
}
CGraphicsRenderer::~CGraphicsRenderer()
{
Clear();
RELEASEOBJECT(m_pDIB);
RELEASEINTERFACE(m_pFontManager);
RELEASEINTERFACE(m_pCache);
}
void CGraphicsRenderer::SetImageCache(NSImages::IImageFilesCache* pCache)
{
RELEASEINTERFACE(m_pCache);
m_pCache = (CImageFilesCache*)pCache;
ADDREFINTERFACE(m_pCache);
}
void CGraphicsRenderer::SetFontManager(NSFonts::IFontManager* pManager)
{
RELEASEINTERFACE(m_pFontManager);
if (NULL == pManager)
{
m_pFontManager = new CFontManager();
m_pFontManager->Initialize();
}
else
{
m_pFontManager = (CFontManager*)pManager;
ADDREFINTERFACE(m_pFontManager);
}
}
void CGraphicsRenderer::CheckFontManager()
{
if (NULL == m_pFontManager)
SetFontManager(NULL);
}
NSFonts::IFontManager* CGraphicsRenderer::GetFontManager()
{
return m_pFontManager;
}
BYTE* CGraphicsRenderer::GetPixels(LONG& lWidth, LONG& lHeight)
{
lWidth = (LONG)m_dPixelsWidth;
lHeight = (LONG)m_dPixelsHeight;
return m_pPixels;
}
void CGraphicsRenderer::ClearInstallFont()
{
m_oInstalledFont.Name = L"";
m_oInstalledFont.Path = L"";
}
void CGraphicsRenderer::SetClipRect(double x, double y, double w, double h)
{
m_pRenderer->SetClipRect3(x, y, w, h);
}
INT CGraphicsRenderer::CheckValidate(INT bOnlyGraphics)
{
if (NULL == m_pRenderer)
return FALSE;
if (!bOnlyGraphics)
return (NULL != m_pPath);
return TRUE;
}
void CGraphicsRenderer::Clear()
{
RELEASEOBJECT(m_pPath);
RELEASEOBJECT(m_pRenderer);
}
void CGraphicsRenderer::UpdateSize()
{
if (NULL == m_pRenderer)
return;
m_pRenderer->SetPageWidth(m_dWidth, Aggplus::UnitMillimeter);
m_pRenderer->SetPageHeight(m_dHeight, Aggplus::UnitMillimeter);
m_pRenderer->SetPageUnit(Aggplus::UnitMillimeter);
}
// тип рендерера-----------------------------------------------------------------------------
HRESULT CGraphicsRenderer::get_Type(LONG* lType)
{
if (NULL == lType)
return S_FALSE;
*lType = c_nGrRenderer;
return S_OK;
}
//-------- Функции для работы со страницей --------------------------------------------------
HRESULT CGraphicsRenderer::NewPage()
{
// ну не влезло так не влезло
return S_OK;
}
HRESULT CGraphicsRenderer::put_Height(const double& dHeight)
{
m_dHeight = dHeight;
if (NULL != m_pRenderer)
{
m_pRenderer->SetPageHeight(m_dHeight, Aggplus::UnitMillimeter);
m_pRenderer->SetPageUnit(Aggplus::UnitMillimeter);
}
return S_OK;
}
HRESULT CGraphicsRenderer::get_Height(double* dHeight)
{
if (NULL == dHeight)
return S_FALSE;
*dHeight = m_dHeight;
return S_OK;
}
HRESULT CGraphicsRenderer::put_Width(const double& dWidth)
{
m_dWidth = dWidth;
if (NULL != m_pRenderer)
{
m_pRenderer->SetPageWidth(m_dWidth, Aggplus::UnitMillimeter);
m_pRenderer->SetPageUnit(Aggplus::UnitMillimeter);
}
return S_OK;
}
HRESULT CGraphicsRenderer::get_Width(double* dWidth)
{
if (NULL == dWidth)
return S_FALSE;
*dWidth = m_dWidth;
return S_OK;
}
HRESULT CGraphicsRenderer::get_DpiX(double* dDpiX)
{
if (NULL == dDpiX)
return S_FALSE;
*dDpiX = 25.4 * m_dPixelsWidth / m_dWidth;
return S_OK;
}
HRESULT CGraphicsRenderer::get_DpiY(double* dDpiY)
{
if (NULL == dDpiY)
return S_FALSE;
*dDpiY = 25.4 * m_dPixelsHeight / m_dHeight;
return S_OK;
}
// pen --------------------------------------------------------------------------------------
HRESULT CGraphicsRenderer::get_PenColor(LONG* lColor)
{
*lColor = m_oPen.Color;
return S_OK;
}
HRESULT CGraphicsRenderer::put_PenColor(const LONG& lColor)
{
m_oPen.Color = lColor;
return S_OK;
}
HRESULT CGraphicsRenderer::get_PenAlpha(LONG* lAlpha)
{
*lAlpha = m_oPen.Alpha;
return S_OK;
}
HRESULT CGraphicsRenderer::put_PenAlpha(const LONG& lAlpha)
{
m_oPen.Alpha = lAlpha;
return S_OK;
}
HRESULT CGraphicsRenderer::get_PenSize(double* dSize)
{
*dSize = m_oPen.Size;
return S_OK;
}
HRESULT CGraphicsRenderer::put_PenSize(const double& dSize)
{
m_oPen.Size = dSize;
return S_OK;
}
HRESULT CGraphicsRenderer::get_PenDashStyle(BYTE* val)
{
*val = m_oPen.DashStyle;
return S_OK;
}
HRESULT CGraphicsRenderer::put_PenDashStyle(const BYTE& val)
{
m_oPen.DashStyle = val;
return S_OK;
}
HRESULT CGraphicsRenderer::get_PenLineStartCap(BYTE* val)
{
*val = m_oPen.LineStartCap;
return S_OK;
}
HRESULT CGraphicsRenderer::put_PenLineStartCap(const BYTE& val)
{
m_oPen.LineStartCap = val;
return S_OK;
}
HRESULT CGraphicsRenderer::get_PenLineEndCap(BYTE* val)
{
*val = m_oPen.LineEndCap;
return S_OK;
}
HRESULT CGraphicsRenderer::put_PenLineEndCap(const BYTE& val)
{
m_oPen.LineEndCap = val;
return S_OK;
}
HRESULT CGraphicsRenderer::get_PenLineJoin(BYTE* val)
{
*val = m_oPen.LineJoin;
return S_OK;
}
HRESULT CGraphicsRenderer::put_PenLineJoin(const BYTE& val)
{
m_oPen.LineJoin = val;
return S_OK;
}
HRESULT CGraphicsRenderer::get_PenDashOffset(double* dOffset)
{
*dOffset = m_oPen.DashOffset;
return S_OK;
}
HRESULT CGraphicsRenderer::put_PenDashOffset(const double& dOffset)
{
m_oPen.DashOffset = dOffset;
return S_OK;
}
HRESULT CGraphicsRenderer::get_PenAlign(LONG* lAlign)
{
*lAlign = m_oPen.Align;
return S_OK;
}
HRESULT CGraphicsRenderer::put_PenAlign(const LONG& lAlign)
{
m_oPen.Align = lAlign;
return S_OK;
}
HRESULT CGraphicsRenderer::get_PenMiterLimit(double* dOffset)
{
*dOffset = m_oPen.MiterLimit;
return S_OK;
}
HRESULT CGraphicsRenderer::put_PenMiterLimit(const double& dOffset)
{
m_oPen.MiterLimit = dOffset;
return S_OK;
}
HRESULT CGraphicsRenderer::PenDashPattern(double* pPattern, LONG lCount)
{
RELEASEARRAYOBJECTS((m_oPen.DashPattern));
m_oPen.DashPattern = new double[lCount];
memcpy(m_oPen.DashPattern, pPattern, lCount * sizeof(double));
m_oPen.Count = lCount;
return S_OK;
}
// brush ------------------------------------------------------------------------------------
HRESULT CGraphicsRenderer::get_BrushType(LONG* lType)
{
*lType = m_oBrush.Type;
return S_OK;
}
HRESULT CGraphicsRenderer::put_BrushType(const LONG& lType)
{
m_oBrush.Type = lType;
return S_OK;
}
HRESULT CGraphicsRenderer::get_BrushColor1(LONG* lColor)
{
*lColor = m_oBrush.Color1;
return S_OK;
}
HRESULT CGraphicsRenderer::put_BrushColor1(const LONG& lColor)
{
m_oBrush.Color1 = lColor;
return S_OK;
}
HRESULT CGraphicsRenderer::get_BrushAlpha1(LONG* lAlpha)
{
*lAlpha = m_oBrush.Alpha1;
return S_OK;
}
HRESULT CGraphicsRenderer::put_BrushAlpha1(const LONG& lAlpha)
{
m_oBrush.Alpha1 = lAlpha;
return S_OK;
}
HRESULT CGraphicsRenderer::get_BrushColor2(LONG* lColor)
{
*lColor = m_oBrush.Color2;
return S_OK;
}
HRESULT CGraphicsRenderer::put_BrushColor2(const LONG& lColor)
{
m_oBrush.Color2 = lColor;
return S_OK;
}
HRESULT CGraphicsRenderer::get_BrushAlpha2(LONG* lAlpha)
{
*lAlpha = m_oBrush.Alpha2;
return S_OK;
}
HRESULT CGraphicsRenderer::put_BrushAlpha2(const LONG& lAlpha)
{
m_oBrush.Alpha2 = lAlpha;
return S_OK;
}
HRESULT CGraphicsRenderer::get_BrushTexturePath(std::wstring* bsPath)
{
*bsPath = m_oBrush.TexturePath;
return S_OK;
}
HRESULT CGraphicsRenderer::put_BrushTexturePath(const std::wstring& bsPath)
{
m_oBrush.TexturePath = bsPath;
return S_OK;
}
HRESULT CGraphicsRenderer::get_BrushTextureImage(Aggplus::CImage** pImage)
{
*pImage = m_oBrush.Image;
return S_OK;
}
HRESULT CGraphicsRenderer::put_BrushTextureImage(Aggplus::CImage *pImage)
{
RELEASEINTERFACE(m_oBrush.Image);
if (NULL == pImage)
return S_OK;
m_oBrush.Image = pImage;
m_oBrush.Image->AddRef();
return S_OK;
}
HRESULT CGraphicsRenderer::get_BrushTextureMode(LONG* lMode)
{
*lMode = m_oBrush.TextureMode;
return S_OK;
}
HRESULT CGraphicsRenderer::put_BrushTextureMode(const LONG& lMode)
{
m_oBrush.TextureMode = lMode;
return S_OK;
}
HRESULT CGraphicsRenderer::get_BrushTextureAlpha(LONG* lTxAlpha)
{
*lTxAlpha = m_oBrush.TextureAlpha;
return S_OK;
}
HRESULT CGraphicsRenderer::put_BrushTextureAlpha(const LONG& lTxAlpha)
{
m_oBrush.TextureAlpha = lTxAlpha;
return S_OK;
}
HRESULT CGraphicsRenderer::get_BrushLinearAngle(double* dAngle)
{
*dAngle = m_oBrush.LinearAngle;
return S_OK;
}
HRESULT CGraphicsRenderer::put_BrushLinearAngle(const double& dAngle)
{
m_oBrush.LinearAngle = dAngle;
return S_OK;
}
HRESULT CGraphicsRenderer::get_BrushTransform(Aggplus::CMatrix &oMatrix)
{
oMatrix = m_oBrush.Transform;
return S_OK;
}
HRESULT CGraphicsRenderer::put_BrushTransform(const Aggplus::CMatrix& oMatrix)
{
m_oBrush.Transform = oMatrix;
return S_OK;
}
HRESULT CGraphicsRenderer::BrushRect(const INT& val, const double& left, const double& top, const double& width, const double& height)
{
m_oBrush.Rectable = val;
m_oBrush.Rect.X = (float)left;
m_oBrush.Rect.Y = (float)top;
m_oBrush.Rect.Width = (float)width;
m_oBrush.Rect.Height = (float)height;
return S_OK;
}
HRESULT CGraphicsRenderer::BrushBounds(const double& left, const double& top, const double& width, const double& height)
{
m_oBrush.Bounds.left = left;
m_oBrush.Bounds.top = top;
m_oBrush.Bounds.right = left + width;
m_oBrush.Bounds.bottom = top + height;
return S_OK;
}
HRESULT CGraphicsRenderer::put_BrushGradientColors(LONG* lColors, double* pPositions, LONG nCount)
{
m_oBrush.m_arrSubColors.clear();
for (LONG i = 0; i < nCount; ++i)
{
NSStructures::CBrush::TSubColor color;
color.color = lColors[i];
color.position = (long)(pPositions[i] * 65536);
m_oBrush.m_arrSubColors.push_back(color);
}
return S_OK;
}
// font -------------------------------------------------------------------------------------
HRESULT CGraphicsRenderer::get_FontName(std::wstring* bsName)
{
*bsName = m_oFont.Name;
return S_OK;
}
HRESULT CGraphicsRenderer::put_FontName(const std::wstring& bsName)
{
m_oFont.Name = bsName;
return S_OK;
}
HRESULT CGraphicsRenderer::get_FontPath(std::wstring* bsName)
{
*bsName = m_oFont.Path;
return S_OK;
}
HRESULT CGraphicsRenderer::put_FontPath(const std::wstring& bsName)
{
m_oFont.Path = bsName;
return S_OK;
}
HRESULT CGraphicsRenderer::get_FontSize(double* dSize)
{
*dSize = m_oFont.Size;
return S_OK;
}
HRESULT CGraphicsRenderer::put_FontSize(const double& dSize)
{
m_oFont.Size = dSize;
return S_OK;
}
HRESULT CGraphicsRenderer::get_FontStyle(LONG* lStyle)
{
*lStyle = m_oFont.GetStyle();
return S_OK;
}
HRESULT CGraphicsRenderer::put_FontStyle(const LONG& lStyle)
{
m_oFont.SetStyle(lStyle);
return S_OK;
}
HRESULT CGraphicsRenderer::get_FontStringGID(INT* bGID)
{
*bGID = m_oFont.StringGID;
return S_OK;
}
HRESULT CGraphicsRenderer::put_FontStringGID(const INT& bGID)
{
m_oFont.StringGID = bGID;
return S_OK;
}
HRESULT CGraphicsRenderer::get_FontCharSpace(double* dSpace)
{
*dSpace = m_oFont.CharSpace;
return S_OK;
}
HRESULT CGraphicsRenderer::put_FontCharSpace(const double& dSpace)
{
m_oFont.CharSpace = dSpace;
return S_OK;
}
HRESULT CGraphicsRenderer::get_FontFaceIndex(int* lFaceIndex)
{
*lFaceIndex = m_oFont.FaceIndex;
return S_OK;
}
HRESULT CGraphicsRenderer::put_FontFaceIndex(const int& lFaceIndex)
{
m_oFont.FaceIndex = lFaceIndex;
return S_OK;
}
//-------- Функции для вывода текста --------------------------------------------------------
HRESULT CGraphicsRenderer::CommandDrawTextCHAR(const LONG& c, const double& x, const double& y, const double& w, const double& h)
{
if (c_nHyperlinkType == m_lCurrentCommandType)
return S_OK;
put_BrushType(c_BrushTypeSolid);
_SetFont();
Aggplus::CBrush* pBrush = CreateBrush(&m_oBrush);
m_pRenderer->DrawStringC(c, m_pFontManager, pBrush, x, y);
RELEASEOBJECT(pBrush);
return S_OK;
}
HRESULT CGraphicsRenderer::CommandDrawText(const std::wstring& bsText, const double& x, const double& y, const double& w, const double& h)
{
if (c_nHyperlinkType == m_lCurrentCommandType)
return S_OK;
put_BrushType(c_BrushTypeSolid);
m_oFont.StringGID = FALSE;
_SetFont();
Aggplus::CBrush* pBrush = CreateBrush(&m_oBrush);
m_pRenderer->DrawString(bsText, m_pFontManager, pBrush, x, y);
RELEASEOBJECT(pBrush);
return S_OK;
}
HRESULT CGraphicsRenderer::CommandDrawTextExCHAR(const LONG& c, const LONG& gid, const double& x, const double& y, const double& w, const double& h)
{
if (gid >= 0)
{
m_oFont.StringGID = TRUE;
return CommandDrawTextCHAR(gid, x, y, w, h);
}
m_oFont.StringGID = FALSE;
return CommandDrawTextCHAR(c, x, y, w, h);
}
HRESULT CGraphicsRenderer::CommandDrawTextEx(const std::wstring& bsUnicodeText, const unsigned int* pGids, const unsigned int nGidsCount, const double& x, const double& y, const double& w, const double& h)
{
if (NULL != pGids && 0 != nGidsCount && !(1 == nGidsCount && 0 == *pGids))
{
m_oFont.StringGID = TRUE;
if (c_nHyperlinkType == m_lCurrentCommandType)
return S_OK;
put_BrushType(c_BrushTypeSolid);
_SetFont();
Aggplus::CBrush* pBrush = CreateBrush(&m_oBrush);
m_pRenderer->DrawString(pGids, nGidsCount, m_pFontManager, pBrush, x, y);
RELEASEOBJECT(pBrush);
return S_OK;
}
m_oFont.StringGID = FALSE;
return CommandDrawText(bsUnicodeText, x, y, w, h);
}
//-------- Маркеры для команд ---------------------------------------------------------------
HRESULT CGraphicsRenderer::BeginCommand(const DWORD& lType)
{
m_lCurrentCommandType = lType;
switch (lType)
{
case c_nPageType:
{
return NewPage();
}
case c_nMaskType:
{
m_pRenderer->StartCreatingAlphaMask();
break;
}
case c_nLayerType:
{
m_pRenderer->CreateLayer();
break;
}
default:
break;
};
return S_OK;
}
HRESULT CGraphicsRenderer::EndCommand(const DWORD& lType)
{
switch (lType)
{
case c_nClipType:
{
INT bIsIn = (c_nClipRegionTypeWinding == (0x0001 & m_lCurrentClipMode));
m_pPath->SetRuler(bIsIn ? false : true);
INT bIsIntersect = (c_nClipRegionIntersect == (0x0100 & m_lCurrentClipMode));
INT bIsStrokePath = (c_nClipToStrokePath == (0x0010 & m_lCurrentClipMode));
m_pRenderer->CombineClip(m_pPath, bIsIntersect ? agg::sbool_and : agg::sbool_or, bIsStrokePath ? &m_oPen : NULL);
//m_pRenderer->SetClip(m_pPath);
break;
}
case c_nResetClipType:
{
m_pRenderer->ResetClip();
m_bIsSetupClip = FALSE;
break;
}
case c_nMaskType:
{
m_pRenderer->EndCreatingAlphaMask();
break;
}
case c_nResetMaskType:
{
m_pRenderer->ResetAlphaMask();
break;
}
case c_nLayerType:
{
m_pRenderer->BlendLayer();
break;
}
default:
break;
};
m_lCurrentCommandType = 0;
return S_OK;
}
//-------- Функции для работы с Graphics Path -----------------------------------------------
HRESULT CGraphicsRenderer::PathCommandMoveTo(const double& x, const double& y)
{
if (!CheckValidate())
return S_FALSE;
m_pPath->MoveTo(x, y);
return S_OK;
}
HRESULT CGraphicsRenderer::PathCommandLineTo(const double& x, const double& y)
{
if (!CheckValidate())
return S_FALSE;
m_pPath->LineTo(x, y);
return S_OK;
}
HRESULT CGraphicsRenderer::PathCommandLinesTo(double* points, const int& count)
{
if (!CheckValidate())
return S_FALSE;
m_pPath->AddLines(points, count);
return S_OK;
}
HRESULT CGraphicsRenderer::PathCommandCurveTo(const double& x1, const double& y1, const double& x2, const double& y2, const double& x3, const double& y3)
{
if (!CheckValidate())
return S_FALSE;
m_pPath->CurveTo(x1, y1, x2, y2, x3, y3);
return S_OK;
}
HRESULT CGraphicsRenderer::PathCommandCurvesTo(double* points, const int& count)
{
if (!CheckValidate())
return S_FALSE;
m_pPath->AddBeziers(points, count);
return S_OK;
}
HRESULT CGraphicsRenderer::PathCommandArcTo(const double& x, const double& y, const double& w, const double& h, const double& startAngle, const double& sweepAngle)
{
if (!CheckValidate())
return S_FALSE;
m_pPath->AddArc2(x, y, w, h, -startAngle, -sweepAngle);
return S_OK;
}
HRESULT CGraphicsRenderer::PathCommandClose()
{
if (!CheckValidate())
return S_FALSE;
m_pPath->CloseFigure();
return S_OK;
}
HRESULT CGraphicsRenderer::PathCommandEnd()
{
if (!CheckValidate())
return S_FALSE;
m_pPath->Reset();
return S_OK;
}
HRESULT CGraphicsRenderer::DrawPath(const LONG& nType)
{
if (!CheckValidate(TRUE))
return S_FALSE;
LONG lFillType = (nType & 0xFF00);
INT bIsStroke = (0x01 == (nType & 0x01));
switch (lFillType)
{
case c_nWindingFillMode:
case c_nEvenOddFillMode:
{
m_pPath->SetRuler((lFillType == c_nWindingFillMode) ? false : true);
CCacheImage* pCacheImage = NULL;
Aggplus::CBrush* pBrush = NULL;
if (m_oBrush.Type == c_BrushTypeTexture)
{
Aggplus::WrapMode oMode = Aggplus::WrapModeClamp;
switch (m_oBrush.TextureMode)
{
case c_BrushTextureModeTile:
oMode = Aggplus::WrapModeTile;
break;
case c_BrushTextureModeTileCenter:
oMode = Aggplus::WrapModeTile;
break;
default:
break;
}
Aggplus::CBrushTexture* pTextureBrush = NULL;
if (NULL != m_oBrush.Image)
{
pTextureBrush = new Aggplus::CBrushTexture(m_oBrush.Image, oMode);
}
else if (m_oBrush.TexturePath.find(L"data:") == 0)
{
bool bIsOnlyOfficeHatch = false;
if (m_oBrush.TexturePath.find(L"onlyoffice_hatch") != std::wstring::npos)
bIsOnlyOfficeHatch = true;
int countErase = (int)(m_oBrush.TexturePath.find(',') + 1);
int nInputSize = (int)(m_oBrush.TexturePath.length() - countErase);
const wchar_t* pInputSrc = m_oBrush.TexturePath.c_str() + countErase;
int nDecodeLen = NSBase64::Base64DecodeGetRequiredLength(nInputSize);
BYTE* pImageData = new BYTE[nDecodeLen];
if (TRUE == NSBase64::Base64Decode(pInputSrc, nInputSize, pImageData, &nDecodeLen))
{
CBgraFrame oFrame;
if (bIsOnlyOfficeHatch)
{
int nSize = (int)sqrt(nDecodeLen >> 2);
oFrame.put_IsRGBA(true);
oFrame.put_Data(pImageData);
oFrame.put_Width(nSize);
oFrame.put_Height(nSize);
oFrame.put_Stride(4 * nSize);
}
else
{
oFrame.put_IsRGBA(false);
oFrame.Decode(pImageData, nDecodeLen);
RELEASEARRAYOBJECTS(pImageData);
}
// pImage отдается pTextureBrush и освобождается вместе с pBrush
Aggplus::CImage* pImage = new Aggplus::CImage();
pImage->Create(oFrame.get_Data(), oFrame.get_Width(), oFrame.get_Height(), oFrame.get_Stride());
oFrame.ClearNoAttack();
pTextureBrush = new Aggplus::CBrushTexture(pImage, oMode);
pTextureBrush->m_bReleaseImage = TRUE;
}
else
RELEASEARRAYOBJECTS(pImageData);
}
else
{
if (NULL != m_pCache)
{
pCacheImage = (CCacheImage*)m_pCache->Lock(m_oBrush.TexturePath);
pTextureBrush = new Aggplus::CBrushTexture(pCacheImage->GetImage(), oMode);
}
else
{
pTextureBrush = new Aggplus::CBrushTexture(m_oBrush.TexturePath, oMode);
}
}
if( pTextureBrush )
{
pTextureBrush->SetTransform(&m_oBrush.Transform);
pTextureBrush->Alpha = (BYTE)m_oBrush.TextureAlpha;
if (m_oBrush.Rectable == 1)
{
pTextureBrush->m_bUseBounds = true;
pTextureBrush->m_oBounds.left = m_oBrush.Rect.X;
pTextureBrush->m_oBounds.top = m_oBrush.Rect.Y;
pTextureBrush->m_oBounds.right = pTextureBrush->m_oBounds.left + m_oBrush.Rect.Width;
pTextureBrush->m_oBounds.bottom = pTextureBrush->m_oBounds.top + m_oBrush.Rect.Height;
}
}
pBrush = pTextureBrush;
}
else
{
pBrush = CreateBrush(&m_oBrush);
}
m_pRenderer->FillPath(pBrush, m_pPath);
RELEASEOBJECT(pBrush);
RELEASEINTERFACE(pCacheImage);
break;
}
default:
break;
};
if (bIsStroke)
{
m_pRenderer->DrawPath(&m_oPen, m_pPath, m_dGammaStroke);
}
return S_OK;
}
HRESULT CGraphicsRenderer::PathCommandStart()
{
if (!CheckValidate())
return S_FALSE;
m_pPath->StartFigure();
return S_OK;
}
HRESULT CGraphicsRenderer::PathCommandGetCurrentPoint(double* x, double* y)
{
if (!CheckValidate())
return S_FALSE;
m_pPath->GetLastPoint(*x, *y);
return S_OK;
}
// textpath
HRESULT CGraphicsRenderer::PathCommandTextCHAR(const LONG& c, const double& x, const double& y, const double& w, const double& h)
{
if (!CheckValidate())
return S_FALSE;
_SetFont();
// так как пат рисуется в миллиметрах - надо перевести пункты в миллиметры
float fSize = (float)(0.3528 * m_oFont.Size);
m_pPath->AddStringC(c, m_pFontManager, x, y);
return S_OK;
}
HRESULT CGraphicsRenderer::PathCommandText(const std::wstring& bsText, const double& x, const double& y, const double& w, const double& h)
{
if (!CheckValidate())
return S_FALSE;
_SetFont();
// так как пат рисуется в миллиметрах - надо перевести пункты в миллиметры
float fSize = (float)(0.3528 * m_oFont.Size);
m_pPath->AddString(bsText, m_pFontManager, x, y);
return S_OK;
}
HRESULT CGraphicsRenderer::PathCommandTextExCHAR(const LONG& c, const LONG& gid, const double& x, const double& y, const double& w, const double& h)
{
if (gid >= 0)
{
m_oFont.StringGID = TRUE;
return PathCommandTextCHAR(gid, x, y, w, h);
}
m_oFont.StringGID = FALSE;
return PathCommandTextCHAR(c, x, y, w, h);
}
HRESULT CGraphicsRenderer::PathCommandTextEx(const std::wstring& bsUnicodeText, const unsigned int* pGids, const unsigned int nGidsCount, const double& x, const double& y, const double& w, const double& h)
{
if (NULL != pGids)
{
m_oFont.StringGID = TRUE;
if (!CheckValidate())
return S_FALSE;
_SetFont();
// так как пат рисуется в миллиметрах - надо перевести пункты в миллиметры
float fSize = (float)(0.3528 * m_oFont.Size);
m_pPath->AddString(pGids, nGidsCount, m_pFontManager, x, y);
return S_OK;
}
m_oFont.StringGID = FALSE;
return PathCommandText(bsUnicodeText, x, y, w, h);
}
//-------- Функции для вывода изображений ---------------------------------------------------
HRESULT CGraphicsRenderer::DrawImage(IGrObject* pImage, const double& x, const double& y, const double& w, const double& h)
{
if (!CheckValidate(TRUE) || NULL == pImage)
return S_FALSE;
m_pRenderer->DrawImage((Aggplus::CImage*)pImage, x, y, w, h);
return S_OK;
}
HRESULT CGraphicsRenderer::DrawImageFromFile(const std::wstring& bstrVal, const double& x, const double& y, const double& w, const double& h, const BYTE& lAlpha)
{
#if 0
MetaFile::CMetaFile oMetafile(m_pFontManager ? m_pFontManager->m_pApplication : NULL);
if (oMetafile.LoadFromFile(bstrVal.c_str()))
{
this->Save();
bool bRet = oMetafile.DrawOnRenderer(this, x, y, w, h);
this->Restore();
return bRet ? S_OK : S_FALSE;
}
#endif
CCacheImage* pCacheImage = NULL;
if (NULL != m_pCache)
{
pCacheImage = (CCacheImage*)m_pCache->Lock(bstrVal);
}
else
{
pCacheImage = new CCacheImage(NULL, bstrVal);
}
if (NULL != pCacheImage)
{
Aggplus::CImage* pImage = pCacheImage->GetImage();
m_pRenderer->DrawImage(pImage, x, y, w, h);
RELEASEINTERFACE(pCacheImage);
}
return S_OK;
}
// transform --------------------------------------------------------------------------------
HRESULT CGraphicsRenderer::SetTransform(const double& m1, const double& m2, const double& m3, const double& m4, const double& m5, const double& m6)
{
if (!CheckValidate())
return S_FALSE;
ApplyTransform(m1, m2, m3, m4, m5, m6);
return S_OK;
}
HRESULT CGraphicsRenderer::GetTransform(double *pdA, double *pdB, double *pdC, double *pdD, double *pdE, double *pdF)
{
if (!CheckValidate())
return S_FALSE;
double buffer[6];
Aggplus::CMatrix oMatrix;
m_pRenderer->GetTransform()->GetElements(buffer);
*pdA = (double)buffer[0];
*pdB = (double)buffer[1];
*pdC = (double)buffer[2];
*pdD = (double)buffer[3];
*pdE = (double)buffer[4];
*pdF = (double)buffer[5];
return S_OK;
}
HRESULT CGraphicsRenderer::ResetTransform()
{
_ResetTransform();
return S_OK;
}
// -----------------------------------------------------------------------------------------
HRESULT CGraphicsRenderer::get_ClipMode(LONG* plMode)
{
*plMode = m_lCurrentClipMode;
return S_OK;
}
HRESULT CGraphicsRenderer::put_ClipMode(const LONG& lMode)
{
if (!CheckValidate())
return S_FALSE;
m_lCurrentClipMode = lMode;
return S_OK;
}
// additiaonal params ----------------------------------------------------------------------
HRESULT CGraphicsRenderer::CommandLong(const LONG& lType, const LONG& lCommand)
{
if (c_nDarkMode == lType && m_pRenderer)
m_pRenderer->m_bIsDarkMode = (1 == lCommand);
if (c_nUseDictionaryFonts == lType && m_pFontManager)
m_pFontManager->SetUseCorrentFontByName((1 == lCommand) ? true : false);
if (c_nPenWidth0As1px == lType && m_pRenderer)
m_pRenderer->m_bIs0PenWidthAs1px = (1 == lCommand) ? true : false;
return S_OK;
}
HRESULT CGraphicsRenderer::CommandDouble(const LONG& lType, const double& dCommand)
{
return S_OK;
}
HRESULT CGraphicsRenderer::CommandString(const LONG& lType, const std::wstring& sCommand)
{
return S_OK;
}
HRESULT CGraphicsRenderer::StartConvertCoordsToIdentity()
{
m_bUseTransformCoordsToIdentity = true;
m_pPath->m_internal->m_pTransform = m_pRenderer->GetFullTransform();
return S_OK;
}
HRESULT CGraphicsRenderer::EndConvertCoordsToIdentity()
{
m_bUseTransformCoordsToIdentity = false;
m_pPath->m_internal->m_pTransform = NULL;
return S_OK;
}
// common
void CGraphicsRenderer::_SetFont()
{
if (m_oInstalledFont.IsEqual(&m_oFont))
{
if (1 < m_dWidth)
{
double dPix = m_oFont.CharSpace * m_dPixelsWidth / m_dWidth;
m_pFontManager->SetCharSpacing(dPix);
}
return;
}
if (1 < m_dWidth)
{
double dPix = m_oFont.CharSpace * m_dPixelsWidth / m_dWidth;
m_pFontManager->m_fCharSpacing = dPix;
}
if (m_oFont.Path.empty())
{
m_pFontManager->LoadFontByName(m_oFont.Name, m_oFont.Size, m_oFont.GetStyle(), m_pRenderer->GetDpiX(), m_pRenderer->GetDpiY());
}
else
{
m_pFontManager->LoadFontFromFile(m_oFont.Path, m_oFont.FaceIndex, m_oFont.Size, m_pRenderer->GetDpiX(), m_pRenderer->GetDpiY());
}
m_pFontManager->m_oString.ResetCTM();
m_pFontManager->SetStringGID(m_oFont.StringGID);
m_pFontManager->SetCharSpacing(m_pFontManager->m_fCharSpacing);
m_oInstalledFont = m_oFont;
}
void CGraphicsRenderer::ApplyTransform(const double& d1, const double& d2, const double& d3, const double& d4, const double& d5, const double& d6)
{
Aggplus::CMatrix oMatrix(d1, d2, d3, d4, d5, d6);
ApplyTransform(&oMatrix);
}
void CGraphicsRenderer::ApplyTransform(Aggplus::CMatrix* pMatrix)
{
if (!CheckValidate())
return;
m_pRenderer->SetTransform(pMatrix);
m_pRenderer->CalculateFullTransform();
}
void CGraphicsRenderer::_ResetTransform()
{
if (!CheckValidate())
return;
ApplyTransform(1, 0, 0, 1, 0, 0);
}
void CGraphicsRenderer::CreateFromBgraFrame(CBgraFrame* pFrame)
{
Aggplus::CDoubleRect oRect;
oRect.left = 0;
oRect.top = 0;
oRect.right = pFrame->get_Width();
oRect.bottom = pFrame->get_Height();
if (pFrame->get_Stride() > 0)
{
CreateFlip(pFrame->get_Data(), oRect, pFrame->get_Width(), pFrame->get_Height());
}
else
{
Create(pFrame->get_Data(), oRect, pFrame->get_Width(), pFrame->get_Height());
}
}
void CGraphicsRenderer::Create(BYTE* pPixels, const Aggplus::CDoubleRect& oRect, LONG lWidthControl, LONG lHeightControl, Aggplus::CDIB* pDib)
{
LONG lRectLeft = (LONG)oRect.left;
LONG lRectTop = (LONG)oRect.top;
LONG lWidth = (LONG)oRect.GetWidth();
LONG lHeight = (LONG)oRect.GetHeight();
m_dPixelsWidth = lWidth;
m_dPixelsHeight = lHeight;
LONG lStride = 4 * lWidthControl;
m_pPixels = pPixels + (4 * lRectLeft);
m_pPixels += lStride * lRectTop;
RELEASEOBJECT(m_pRenderer);
RELEASEOBJECT(m_pPath);
m_pRenderer = new Aggplus::CGraphics();
m_pPath = new Aggplus::CGraphicsPath();
m_lClipLeft = (std::max)(0, (int) lRectLeft);
m_lClipTop = (std::max)(0, (int) lRectTop);
//LONG lClipRight = min(lWidth, -lRectLeft + lWidthControl);
//LONG lClipBottom = min(lHeight, -lRectTop + lHeightControl);
LONG lClipRight = (std::min)((LONG)oRect.right, lWidthControl);
LONG lClipBottom = (std::min)((LONG)oRect.bottom, lHeightControl);
m_lClipWidth = lClipRight - m_lClipLeft;
m_lClipHeight = lClipBottom - m_lClipTop;
m_pRenderer->Create2(pPixels, lWidthControl, lHeightControl, -4 * lWidthControl, 0,
m_lClipLeft, m_lClipTop, m_lClipWidth, m_lClipHeight, oRect.GetWidth(), oRect.GetHeight(), pDib);
Aggplus::CMatrix oBase(1, 0, 0, 1, oRect.left, oRect.top);
m_pRenderer->SetBaseTransform(&oBase);
m_pRenderer->SetPageWidth(m_dWidth, Aggplus::UnitMillimeter);
m_pRenderer->SetPageHeight(m_dHeight, Aggplus::UnitMillimeter);
m_pRenderer->SetPageUnit(Aggplus::UnitMillimeter);
}
void CGraphicsRenderer::CreateFlip(BYTE* pPixels, const Aggplus::CDoubleRect& oRect, LONG lWidthControl, LONG lHeightControl, Aggplus::CDIB* pDib)
{
LONG lRectLeft = (LONG)oRect.left;
LONG lRectTop = (LONG)oRect.top;
LONG lWidth = (LONG)oRect.GetWidth();
LONG lHeight = (LONG)oRect.GetHeight();
m_dPixelsWidth = lWidth;
m_dPixelsHeight = lHeight;
LONG lStride = 4 * lWidthControl;
RELEASEOBJECT(m_pRenderer);
RELEASEOBJECT(m_pPath);
m_pRenderer = new Aggplus::CGraphics();
m_pPath = new Aggplus::CGraphicsPath();
m_lClipLeft = (std::max) (0, (int) lRectLeft);
m_lClipTop = (std::max) (0, (int) lRectTop);
//LONG lClipRight = min(lWidth, -lRectLeft + lWidthControl);
//LONG lClipBottom = min(lHeight, -lRectTop + lHeightControl);
LONG lClipRight = (std::min) ((LONG)oRect.right, lWidthControl);
LONG lClipBottom = (std::min) ((LONG)oRect.bottom, lHeightControl);
m_lClipWidth = lClipRight - m_lClipLeft;
m_lClipHeight = lClipBottom - m_lClipTop;
//m_pRenderer->Create(m_pPixels, lWidth, lHeight, -4 * lWidthControl, 0, colorModeRGBA8);
m_pRenderer->Create2(pPixels, lWidthControl, lHeightControl, 4 * lWidthControl, 0,
m_lClipLeft, m_lClipTop, m_lClipWidth, m_lClipHeight, oRect.GetWidth(), oRect.GetHeight(), pDib);
Aggplus::CMatrix oBase(1, 0, 0, 1, oRect.left, oRect.top);
m_pRenderer->SetBaseTransform(&oBase);
m_pRenderer->SetPageWidth(m_dWidth, Aggplus::UnitMillimeter);
m_pRenderer->SetPageHeight(m_dHeight, Aggplus::UnitMillimeter);
m_pRenderer->SetPageUnit(Aggplus::UnitMillimeter);
}
void CGraphicsRenderer::SetAlphaMask(Aggplus::CAlphaMask *pAlphaMask)
{
m_pRenderer->SetAlphaMask(pAlphaMask);
}
Aggplus::CSoftMask* CGraphicsRenderer::CreateSoftMask(bool bAlpha)
{
return m_pRenderer->CreateSoftMask(bAlpha);
}
void CGraphicsRenderer::SetSoftMask(Aggplus::CSoftMask* pSoftMask)
{
m_pRenderer->SetSoftMask(pSoftMask);
}
HRESULT CGraphicsRenderer::put_LayerOpacity(double dValue)
{
return m_pRenderer->SetLayerOpacity(dValue);
}
void CGraphicsRenderer::put_GlobalAlphaEnabled(const bool& bEnabled, const double& dVal)
{
m_bGlobalAlphaEnabled = bEnabled;
if (m_bGlobalAlphaEnabled)
m_dGlobalAlpha = dVal;
else
m_dGlobalAlpha = 1.0;
m_pRenderer->m_dGlobalAlpha = m_dGlobalAlpha;
}
void CGraphicsRenderer::AddRect(const double& x, const double& y, const double& w, const double& h)
{
if (!CheckValidate())
return;
m_pPath->MoveTo(x, y);
m_pPath->LineTo(x + w, y);
m_pPath->LineTo(x + w, y + h);
m_pPath->LineTo(x, y + h);
m_pPath->CloseFigure();
}
void CGraphicsRenderer::SetGammaStroke(double value)
{
m_dGammaStroke = value;
}
// SAVE/RESTORE section
class CGraphicsRenderer_State : public IGraphicsRenderer_State
{
public:
CGraphicsRenderer_State() : IGraphicsRenderer_State()
{
}
CGraphicsRenderer_State(const Aggplus::CGraphics_ClipState& oState) : IGraphicsRenderer_State(), m_oClipState(oState)
{
}
virtual ~CGraphicsRenderer_State()
{
}
public:
NSStructures::CPen m_oPen;
NSStructures::CBrush m_oBrush;
NSStructures::CFont m_oFont;
Aggplus::CMatrix m_oTransform;
double m_dGlobalAlpha;
bool m_bGlobalAlphaEnabled;
bool m_bIntegerGrid;
unsigned int m_nBlendMode;
Aggplus::CGraphics_ClipState m_oClipState;
};
void CGraphicsRenderer::Save()
{
if (!m_pRenderer)
return;
CGraphicsRenderer_State* pState = new CGraphicsRenderer_State(m_pRenderer->m_oClipState);
pState->m_oPen = m_oPen;
pState->m_oBrush = m_oBrush;
pState->m_oFont = m_oFont;
pState->m_oTransform = *m_pRenderer->GetTransform();
pState->m_dGlobalAlpha = m_dGlobalAlpha;
pState->m_bGlobalAlphaEnabled = m_bGlobalAlphaEnabled;
pState->m_bIntegerGrid = m_pRenderer->m_bIntegerGrid;
pState->m_nBlendMode = m_pRenderer->m_nBlendMode;
m_arStates.push_back(pState);
}
void CGraphicsRenderer::Restore()
{
if (!m_pRenderer)
return;
if (0 == m_arStates.size())
return;
CGraphicsRenderer_State* pState = (CGraphicsRenderer_State*)m_arStates.at(m_arStates.size() - 1);
m_arStates.pop_back();
m_oPen = pState->m_oPen;
m_oBrush = pState->m_oBrush;
m_oFont = pState->m_oFont;
ApplyTransform(&pState->m_oTransform);
this->put_IntegerGrid(pState->m_bIntegerGrid);
this->put_GlobalAlphaEnabled(pState->m_bGlobalAlphaEnabled, pState->m_dGlobalAlpha);
this->put_BlendMode(pState->m_nBlendMode);
m_pRenderer->ResetClip();
for (std::vector<Aggplus::CGraphics_ClipStateRecord*>::iterator i = pState->m_oClipState.Records.begin(); i != pState->m_oClipState.Records.end(); i++)
{
Aggplus::CGraphics_ClipStateRecord* pRecord = *i;
m_pRenderer->InternalClip(pRecord->Path, pRecord->Transform, pRecord->Operation);
}
RELEASEOBJECT(pState);
}
void CGraphicsRenderer::put_BlendMode(const unsigned int& nBlendMode)
{
if (NULL != m_pRenderer)
{
m_pRenderer->m_nBlendMode = nBlendMode;
}
}