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

402 lines
11 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 "Shading.h"
namespace PdfWriter
{
//----------------------------------------------------------------------------------------
// CLinearFuntion
//----------------------------------------------------------------------------------------
class CLinearFuntion : public CDictObject
{
public:
CLinearFuntion(CXref* pXref, double* pC0Values, double* pC1Values, int nCount)
{
if (!nCount || !pC0Values || !pC1Values)
return;
pXref->Add(this);
Add("FunctionType", 2);
CArrayObject* pDomain = new CArrayObject();
if (!pDomain)
return;
pDomain->Add(0.0);
pDomain->Add(1.0);
Add("Domain", pDomain);
CArrayObject* pC0Array = new CArrayObject();
if (!pC0Array)
return;
Add("C0", pC0Array);
CArrayObject* pC1Array = new CArrayObject();
if (!pC1Array)
return;
Add("C1", pC1Array);
Add("N", 1);
for (int nIndex = 0; nIndex < nCount; nIndex++)
{
pC0Array->Add(pC0Values[nIndex]);
pC1Array->Add(pC1Values[nIndex]);
}
}
};
//----------------------------------------------------------------------------------------
// CLineSegmentFuntion
//----------------------------------------------------------------------------------------
class CLineSegmentFuntion : public CDictObject
{
public:
CLineSegmentFuntion(CXref* pXref, double** ppValues, double* pPoints, int nFunctionsCount, int nOutputDimension)
{
pXref->Add(this);
Add("FunctionType", 3);
CArrayObject* pDomain = new CArrayObject();
if (!pDomain)
return;
pDomain->Add(0.0);
pDomain->Add(1.0);
Add("Domain", pDomain);
CArrayObject* pFunctions = new CArrayObject();
if (!pFunctions)
return;
Add("Functions", pFunctions);
CArrayObject* pBounds = new CArrayObject();
if (!pBounds)
return;
Add("Bounds", pBounds);
CArrayObject* pEncode = new CArrayObject();
if (!pEncode)
return;
Add("Encode", pEncode);
for (int nFunctionIndex = 0; nFunctionIndex < nFunctionsCount; nFunctionIndex++)
{
CLinearFuntion* pFunc = new CLinearFuntion(pXref, ppValues[2 * nFunctionIndex], ppValues[2 * nFunctionIndex + 1], nOutputDimension);
pFunctions->Add(pFunc);
pEncode->Add(0.0);
pEncode->Add(1.0);
if (nFunctionIndex != nFunctionsCount - 1)
pBounds->Add(pPoints[nFunctionIndex]);
}
}
};
//----------------------------------------------------------------------------------------
// CShading
//----------------------------------------------------------------------------------------
CShading::CShading(CXref* pXref)
{
m_pXref = pXref;
pXref->Add(this);
m_bRgb = true;
m_pColors = NULL;
m_pColorsPoints = NULL;
m_nColorsCount = 0;
m_bBeginExtend = false;
m_bEndExtend = false;
}
CShading::~CShading()
{
if (m_pColors)
delete[] m_pColors;
if (m_pColorsPoints)
delete[] m_pColorsPoints;
}
void CShading::SetRgbColors(unsigned char* pColors, double* pPoints, int nCount)
{
if (!pColors || !pPoints || nCount <= 1)
return;
m_bRgb = true;
m_pColors = new unsigned char[3 * nCount];
m_pColorsPoints = new double[nCount];
m_nColorsCount = nCount;
if (!m_pColors || !m_pColorsPoints)
return;
for (int nIndex = 0; nIndex < nCount; nIndex++)
{
m_pColors[3 * nIndex + 0] = pColors[3 * nIndex + 0];
m_pColors[3 * nIndex + 1] = pColors[3 * nIndex + 1];
m_pColors[3 * nIndex + 2] = pColors[3 * nIndex + 2];
m_pColorsPoints[nIndex] = pPoints[nIndex];
}
Add("ColorSpace", "DeviceRGB");
CArrayObject* pDomain = new CArrayObject();
if (!pDomain)
return;
pDomain->Add(0.0);
pDomain->Add(1.0);
Add("Domain", pDomain);
if (nCount <= 2)
{
double pC0Values[] ={
pColors[0] / 255.0,
pColors[1] / 255.0,
pColors[2] / 255.0
};
double pC1Values[] ={
pColors[3] / 255.0,
pColors[4] / 255.0,
pColors[5] / 255.0
};
CLinearFuntion* pFunction = new CLinearFuntion(m_pXref, pC0Values, pC1Values, 3);
Add("Function", pFunction);
}
else
{
double** ppValues = new double*[(nCount - 1) * 2];
for (int nIndex = 0; nIndex < nCount - 1; nIndex++)
{
ppValues[2 * nIndex + 0] = new double[3];
ppValues[2 * nIndex + 1] = new double[3];
ppValues[2 * nIndex + 0][0] = pColors[3 * nIndex + 0] / 255.0;
ppValues[2 * nIndex + 0][1] = pColors[3 * nIndex + 1] / 255.0;
ppValues[2 * nIndex + 0][2] = pColors[3 * nIndex + 2] / 255.0;
ppValues[2 * nIndex + 1][0] = pColors[3 * (nIndex + 1) + 0] / 255.0;
ppValues[2 * nIndex + 1][1] = pColors[3 * (nIndex + 1) + 1] / 255.0;
ppValues[2 * nIndex + 1][2] = pColors[3 * (nIndex + 1) + 2] / 255.0;
}
CLineSegmentFuntion* pFunction = new CLineSegmentFuntion(m_pXref, ppValues, pPoints + 1, nCount - 1, 3);
Add("Function", pFunction);
for (int nIndex = 0; nIndex < nCount - 1; nIndex++)
{
delete[] ppValues[2 * nIndex + 0];
delete[] ppValues[2 * nIndex + 1];
}
delete[] ppValues;
}
}
void CShading::SetGrayColors(unsigned char* pColors, double* pPoints, int nCount)
{
if (!pColors || !pPoints || nCount <= 1)
return;
m_bRgb = false;
m_pColors = new unsigned char[nCount];
m_pColorsPoints = new double[nCount];
m_nColorsCount = nCount;
if (!m_pColors || !m_pColorsPoints)
return;
memcpy(m_pColors, pColors, nCount);
Add("ColorSpace", "DeviceGray");
CArrayObject* pDomain = new CArrayObject();
if (!pDomain)
return;
pDomain->Add(0.0);
pDomain->Add(1.0);
Add("Domain", pDomain);
if (nCount <= 2)
{
double pC0Values = pColors[0] / 255.0;
double pC1Values = pColors[1] / 255.0;
CLinearFuntion* pFunction = new CLinearFuntion(m_pXref, &pC0Values, &pC1Values, 1);
Add("Function", pFunction);
}
else
{
double* pValues = new double[(nCount - 1) * 2];
if (pValues)
{
for (int nIndex = 0; nIndex < nCount - 1; nIndex++)
{
pValues[2 * nIndex + 0] = pColors[nIndex] / 255.0;
pValues[2 * nIndex + 1] = pColors[nIndex + 1] / 255.0;
}
CLineSegmentFuntion* pFunction = new CLineSegmentFuntion(m_pXref, &pValues, pPoints + 1, nCount - 1, 1);
Add("Function", pFunction);
delete[] pValues;
}
}
}
void CShading::SetExtend(bool bBegin, bool bEnd)
{
CArrayObject* pExtend = new CArrayObject();
if (!pExtend)
return;
pExtend->Add(bBegin);
pExtend->Add(bEnd);
Add("Extend", pExtend);
m_bBeginExtend = bBegin;
m_bEndExtend = bEnd;
}
bool CShading::CompareColors(unsigned char* pColors, double* pPoints, int nCount, bool bRgb)
{
if (nCount != m_nColorsCount
|| (pColors && !m_pColors)
|| (pPoints && !m_pColorsPoints)
|| (!pColors && m_pColors)
|| (!pPoints && m_pColorsPoints)
|| bRgb != m_bRgb)
return false;
if (m_bRgb)
{
for (int nIndex = 0; nIndex < nCount; nIndex++)
{
if (pColors[3 * nIndex + 0] != m_pColors[3 * nIndex + 0]
|| pColors[3 * nIndex + 1] != m_pColors[3 * nIndex + 1]
|| pColors[3 * nIndex + 2] != m_pColors[3 * nIndex + 2]
|| fabs(pPoints[nIndex] - m_pColorsPoints[nIndex]) > 0.01)
return false;
}
}
else
{
for (int nIndex = 0; nIndex < nCount; nIndex++)
{
if (pColors[nIndex] != m_pColors[nIndex]
|| fabs(pPoints[nIndex] - m_pColorsPoints[nIndex]) > 0.01)
return false;
}
}
return true;
}
bool CShading::CompareExtend(bool bBegin, bool bEnd)
{
if (bBegin != m_bBeginExtend || bEnd != m_bEndExtend)
return false;
return true;
}
//----------------------------------------------------------------------------------------
// CAxialShading
//----------------------------------------------------------------------------------------
CAxialShading::CAxialShading(CXref* pXref, double dX0, double dY0, double dX1, double dY1) : CShading(pXref)
{
Add("ShadingType", 2);
CArrayObject* pCoords = new CArrayObject();
if (!pCoords)
return;
pCoords->Add(dX0);
pCoords->Add(dY0);
pCoords->Add(dX1);
pCoords->Add(dY1);
Add("Coords", pCoords);
m_dX0 = dX0;
m_dY0 = dY0;
m_dX1 = dX1;
m_dY1 = dY1;
}
bool CAxialShading::Compare(double dX0, double dY0, double dX1, double dY1)
{
if (fabs(dX0 - m_dX0) > 0.01
|| fabs(dY0 - m_dY0) > 0.01
|| fabs(dX1 - m_dX1) > 0.01
|| fabs(dY1 - m_dY1) > 0.01)
return false;
return true;
}
//----------------------------------------------------------------------------------------
// CRadialShading
//----------------------------------------------------------------------------------------
CRadialShading::CRadialShading(CXref* pXref, double dX0, double dY0, double dR0, double dX1, double dY1, double dR1) : CShading(pXref)
{
Add("ShadingType", 3);
CArrayObject* pCoords = new CArrayObject();
if (!pCoords)
return;
pCoords->Add(dX0);
pCoords->Add(dY0);
pCoords->Add(dR0);
pCoords->Add(dX1);
pCoords->Add(dY1);
pCoords->Add(dR1);
Add("Coords", pCoords);
m_dX0 = dX0;
m_dY0 = dY0;
m_dR0 = dR0;
m_dX1 = dX1;
m_dY1 = dY1;
m_dR1 = dR1;
}
bool CRadialShading::Compare(double dX0, double dY0, double dR0, double dX1, double dY1, double dR1)
{
if (fabs(dX0 - m_dX0) > 0.01
|| fabs(dY0 - m_dY0) > 0.01
|| fabs(dR0 - m_dR0) > 0.01
|| fabs(dX1 - m_dX1) > 0.01
|| fabs(dY1 - m_dY1) > 0.01
|| fabs(dR1 - m_dR1) > 0.01)
return false;
return true;
}
}