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

2559 lines
66 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* (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 "Annotation.h"
#include "Pages.h"
#include "Utils.h"
#include "ResourcesDictionary.h"
#include "FontCidTT.h"
#include "Streams.h"
#include "Image.h"
#include "../../DesktopEditor/common/File.h"
#ifndef BS_DEF_WIDTH
#define BS_DEF_WIDTH 1
#endif
namespace PdfWriter
{
const static char* c_sAnnotTypeNames[] =
{
"Text",
"Link",
"FreeText",
"Line",
"Square",
"Circle",
"Polygon",
"PolyLine",
"Highlight",
"Underline",
"Squiggly",
"StrikeOut",
"Stamp",
"Caret",
"Ink",
"Popup",
"FileAttachment",
"Sound",
"Movie",
"Widget",
"Screen",
"PrinterMark",
"TrapNet",
"Watermark",
"3D",
"Redact"
};
const static char* c_sAnnotIconNames[] =
{
"Check", "Checkmark", "Circle", "Comment", "Cross", "CrossHairs", "Help", "Insert", "Key", "NewParagraph", "Note", "Paragraph", "RightArrow", "RightPointer", "Star", "UpArrow", "UpLeftArrow"
};
const static char* c_sCheckBoxStyleNames[] =
{
"4", // Check
"8", // Cross
"u", // Diamond
"l", // Circle
"H", // Star
"n" // Square
};
void AddToVectorD(CDictObject* pObj, const std::string& sName, const std::vector<double>& arrV)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
pObj->Add(sName, pArray);
for (const double& dV : arrV)
pArray->Add(dV);
}
std::string AddLE(const BYTE& nLE)
{
std::string sValue;
ELineEndType eLE = ELineEndType(nLE);
switch (eLE)
{
case ELineEndType::Square: sValue = "Square"; break;
case ELineEndType::Circle: sValue = "Circle"; break;
case ELineEndType::Diamond: sValue = "Diamond"; break;
case ELineEndType::OpenArrow: sValue = "OpenArrow"; break;
case ELineEndType::ClosedArrow: sValue = "ClosedArrow"; break;
case ELineEndType::None: sValue = "None"; break;
case ELineEndType::Butt: sValue = "Butt"; break;
case ELineEndType::ROpenArrow: sValue = "ROpenArrow"; break;
case ELineEndType::RClosedArrow: sValue = "RClosedArrow"; break;
case ELineEndType::Slash: sValue = "Slash"; break;
}
return sValue;
}
void AddRD(CDictObject* pObj, const double& dRD1, const double& dRD2, const double& dRD3, const double& dRD4)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
pObj->Add("RD", pArray);
pArray->Add(dRD1);
pArray->Add(dRD4);
pArray->Add(dRD3);
pArray->Add(dRD2);
}
std::string GetColor(const std::vector<double>& arr, bool bCaps, double dDiff = 0)
{
if (arr.empty())
return bCaps ? "1 G" : "1 g";
std::string sDA;
for (double dColoc : arr)
{
sDA.append(std::to_string(dColoc + dDiff));
sDA.append(" ");
}
if (arr.size() == 3)
sDA.append(bCaps ? "RG" : "rg");
else if (arr.size() == 4)
sDA.append(bCaps ? "K" : "k");
else if (arr.size() == 1)
sDA.append(bCaps ? "G" : "g");
return sDA;
}
std::string GetColor(CArrayObject* pArr, bool bCAPS, float dDiff = 0)
{
std::string sDA;
if (!pArr)
return sDA;
int nSize = pArr->GetCount();
for (int i = 0; i < nSize; ++i)
{
CObjectBase* pColor = pArr->Get(i);
float fColor = pColor->GetType() == object_type_REAL ? ((CRealObject*)pColor)->Get() : ((CNumberObject*)pColor)->Get();
sDA.append(std::to_string(fColor + dDiff));
sDA.append(" ");
}
if (nSize == 3)
sDA.append(bCAPS ? "RG" : "rg");
else if (nSize == 4)
sDA.append(bCAPS ? "K" : "k");
else if (nSize == 1)
sDA.append(bCAPS ? "G" : "g");
return sDA;
}
//----------------------------------------------------------------------------------------
// CAnnotation
//----------------------------------------------------------------------------------------
CAnnotation::CAnnotation(CXref* pXref, EAnnotType eType)
{
m_pAppearance = NULL;
m_pDocument = NULL;
m_pXref = pXref;
m_oBorder.bHave = false;
Add("Type", "Annot");
Add("Subtype", c_sAnnotTypeNames[(int)eType]);
// Для PDFA нужно, чтобы 0, 1, 4 биты были выключены, а второй включен
Add("F", 4);
}
void CAnnotation::SetRect(const TRect& oRect)
{
m_oRect = oRect;
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("Rect", pArray);
if (oRect.fTop < oRect.fBottom)
{
m_oRect.fTop = oRect.fBottom;
m_oRect.fBottom = oRect.fTop;
}
pArray->Add(m_oRect.fLeft);
pArray->Add(m_oRect.fBottom);
pArray->Add(m_oRect.fRight);
pArray->Add(m_oRect.fTop);
}
void CAnnotation::SetBorder(BYTE nType, double dWidth, const std::vector<double>& arrDash)
{
CDictObject* pBorderStyleDict = new CDictObject();
if (!pBorderStyleDict)
return;
Add("BS", pBorderStyleDict);
pBorderStyleDict->Add("Type", "Border");
pBorderStyleDict->Add("W", dWidth);
EBorderType eBT = EBorderType(nType);
if (EBorderType::Dashed == eBT)
AddToVectorD(pBorderStyleDict, "D", arrDash);
switch (eBT)
{
case EBorderType::Solid: pBorderStyleDict->Add("S", "S"); break;
case EBorderType::Dashed: pBorderStyleDict->Add("S", "D"); break;
case EBorderType::Beveled: pBorderStyleDict->Add("S", "B"); break;
case EBorderType::Inset: pBorderStyleDict->Add("S", "I"); break;
case EBorderType::Underline: pBorderStyleDict->Add("S", "U"); break;
}
m_oBorder.bHave = true;
m_oBorder.nType = EBorderType(nType);
m_oBorder.dWidth = dWidth;
m_oBorder.arrDash = arrDash;
}
void CAnnotation::SetAnnotFlag(const int& nAnnotFlag)
{
Add("F", nAnnotFlag);
}
void CAnnotation::SetPage(CPage* pPage, double dW, double dH, double dX, double dY)
{
Add("P", pPage);
m_dPageW = dW;
m_dPageH = dH;
m_dPageX = dX;
m_dPageY = dY;
}
void CAnnotation::SetBE(BYTE nType, const double& dBE)
{
CDictObject* pBEDict = new CDictObject();
if (!pBEDict)
return;
Add("BE", pBEDict);
pBEDict->Add("I", dBE);
std::string sValue;
switch (nType)
{
case 0:
{ sValue = "S"; break; }
case 1:
{ sValue = "C"; break; }
default: { return; }
}
pBEDict->Add("S", sValue.c_str());
}
void CAnnotation::SetContents(const std::wstring& wsText)
{
std::string sValue = U_TO_UTF8(wsText);
Add("Contents", new CStringObject(sValue.c_str(), true));
// TODO
Remove("RC");
}
void CAnnotation::SetNM(const std::wstring& wsNM)
{
std::string sValue = U_TO_UTF8(wsNM);
Add("NM", new CStringObject(sValue.c_str()));
}
void CAnnotation::SetLM(const std::wstring& wsLM)
{
std::string sValue = U_TO_UTF8(wsLM);
Add("M", new CStringObject(sValue.c_str()));
}
void CAnnotation::SetOUserID(const std::wstring& wsLM)
{
std::string sValue = U_TO_UTF8(wsLM);
Add("OUserID", new CStringObject(sValue.c_str()));
}
void CAnnotation::SetOMetadata(const std::wstring& wsOMetadata)
{
std::string sValue = U_TO_UTF8(wsOMetadata);
Add("OMetadata", new CStringObject(sValue.c_str(), true));
}
void CAnnotation::SetC(const std::vector<double>& arrC)
{
AddToVectorD(this, "C", arrC);
}
void CAnnotation::SetDocument(CDocument* pDocument)
{
m_pDocument = pDocument;
}
CDocument* CAnnotation::GetDocument()
{
return m_pDocument;
}
std::string CAnnotation::GetBorderDash()
{
std::string sRes = "[";
for (double dDash : m_oBorder.arrDash)
{
sRes.append(" ");
sRes.append(std::to_string(dDash));
}
sRes.append(" ] 0 d\012");
return sRes;
}
std::string CAnnotation::GetColorName(const std::string& sName, bool bCAPS)
{
std::string sRes;
CObjectBase* pObj = Get(sName);
if (pObj && pObj->GetType() == object_type_ARRAY)
{
sRes += GetColor(dynamic_cast<CArrayObject*>(pObj), bCAPS).c_str();
sRes += "\012";
}
return sRes;
}
CAnnotAppearanceObject* CAnnotation::StartAP(int nRotate)
{
m_pAppearance = new CAnnotAppearance(m_pXref, this);
if (!m_pAppearance)
return NULL;
Add("AP", m_pAppearance);
CResourcesDict* pResources = new CResourcesDict(m_pXref, false, false);
CAnnotAppearanceObject* pNormal = m_pAppearance->GetNormal(pResources);
pNormal->Add("Resources", pResources);
return pNormal;
}
void CAnnotation::APFromFakePage()
{
if (!m_pAppearance)
return;
CAnnotAppearanceObject* pNormal = m_pAppearance->GetNormal();
pNormal->AddBBox(GetRect().fLeft, GetRect().fBottom, GetRect().fRight, GetRect().fTop);
pNormal->AddMatrix(1, 0, 0, 1, -GetRect().fLeft, -GetRect().fBottom);
}
//----------------------------------------------------------------------------------------
// CMarkupAnnotation
//----------------------------------------------------------------------------------------
CMarkupAnnotation::CMarkupAnnotation(CXref* pXref, EAnnotType eType) : CAnnotation(pXref, eType)
{
}
void CMarkupAnnotation::SetRT(BYTE nRT)
{
Add("RT", nRT ? "Group" : "R");
}
CPopupAnnotation* CMarkupAnnotation::CreatePopup()
{
CPopupAnnotation* pAnnot = new CPopupAnnotation(m_pXref);
m_pXref->Add(pAnnot);
Add("Popup", pAnnot);
pAnnot->SetOpen(false);
pAnnot->SetParentID(this);
pAnnot->SetAnnotFlag(28);
TRect oRect = m_oRect;
oRect.fLeft = m_dPageW - 100 - (oRect.fRight - oRect.fLeft);
oRect.fBottom -= 100;
oRect.fRight = m_dPageW;
pAnnot->SetRect(oRect);
return pAnnot;
}
void CMarkupAnnotation::SetCA(const double& dCA)
{
Add("CA", dCA);
}
void CMarkupAnnotation::SetT(const std::wstring& wsT)
{
std::string sValue = U_TO_UTF8(wsT);
if (!Get("T"))
Add("T", new CStringObject(sValue.c_str(), true));
}
void CMarkupAnnotation::SetRC(const std::wstring& wsRC)
{
std::string sValue = U_TO_UTF8(wsRC);
Add("RC", new CStringObject(sValue.c_str(), true));
}
void CMarkupAnnotation::SetCD(const std::wstring& wsCD)
{
std::string sValue = U_TO_UTF8(wsCD);
Add("CreationDate", new CStringObject(sValue.c_str()));
}
void CMarkupAnnotation::SetSubj(const std::wstring& wsSubj)
{
std::string sValue = U_TO_UTF8(wsSubj);
Add("Subj", new CStringObject(sValue.c_str(), true));
}
void CMarkupAnnotation::SetIRTID(CAnnotation* pAnnot)
{
Add("IRT", pAnnot);
}
void CMarkupAnnotation::RemoveAP()
{
Remove("AP");
}
//----------------------------------------------------------------------------------------
// CLinkAnnotation
//----------------------------------------------------------------------------------------
CLinkAnnotation::CLinkAnnotation(CXref* pXref, CDestination* pDestination) : CAnnotation(pXref, AnnotLink)
{
Add("Dest", (CObjectBase*)pDestination);
}
void CLinkAnnotation::SetBorderStyle(float fWidth, unsigned short nDashOn, unsigned short nDashOff)
{
fWidth = std::max(fWidth, 0.f);
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("Border", pArray);
pArray->Add(0);
pArray->Add(0);
pArray->Add(fWidth);
if (nDashOn && nDashOff)
{
CArrayObject* pDash = new CArrayObject();
if (!pDash)
return;
pArray->Add(pDash);
pDash->Add(nDashOn);
pDash->Add(nDashOff);
}
}
void CLinkAnnotation::SetHighlightMode(EAnnotHighlightMode eMode)
{
switch (eMode)
{
case AnnotNoHighlight: Add("H", "N"); break;
case AnnotInvertBorder: Add("H", "O"); break;
case AnnotDownAppearance: Add("H", "P"); break;
default: Remove("H"); break;
}
}
//----------------------------------------------------------------------------------------
// CTextAnnotation
//----------------------------------------------------------------------------------------
CTextAnnotation::CTextAnnotation(CXref* pXref) : CMarkupAnnotation(pXref, AnnotText)
{
m_nName = 10;
Add("Name", "Comment");
}
void CTextAnnotation::SetOpen(bool bOpen)
{
Add("Open", new CBoolObject(bOpen));
}
void CTextAnnotation::SetName(BYTE nName)
{
m_nName = nName;
Add("Name", c_sAnnotIconNames[nName]);
}
void CTextAnnotation::SetState(BYTE nState)
{
std::string sValue;
switch (nState)
{
case 0:
{ sValue = "Marked"; break; }
case 1:
{ sValue = "Unmarked"; break; }
case 2:
{ sValue = "Accepted"; break; }
case 3:
{ sValue = "Rejected"; break; }
case 4:
{ sValue = "Cancelled"; break; }
case 5:
{ sValue = "Completed"; break; }
case 6:
{ sValue = "None"; break; }
default: { return; }
}
Add("State", new CStringObject(sValue.c_str()));
if (!Get("C"))
SetC({ 1.0, 0.8, 0.0 });
}
void CTextAnnotation::SetStateModel(BYTE nStateModel)
{
std::string sValue;
switch (nStateModel)
{
case 0:
{ sValue = "Marked"; break; }
case 1:
{ sValue = "Review"; break; }
default: { return; }
}
Add("StateModel", new CStringObject(sValue.c_str()));
}
void CTextAnnotation::SetAP()
{
std::string sColor = GetColor(dynamic_cast<CArrayObject*>(Get("C")), false);
CAnnotAppearance* pAP = new CAnnotAppearance(m_pXref, this);
Add("AP", pAP);
CAnnotAppearanceObject* pN = pAP->GetNormal();
CAnnotAppearanceObject* pR = pAP->GetRollover();
switch (m_nName)
{
case 0:
{
pN->AddBBox(0, 0, 19, 19);
pN->DrawTextCheck(sColor);
pR->AddBBox(0, 0, 19, 19);
pR->DrawTextCheck(sColor);
break;
}
case 1:
{
pN->AddBBox(0, 0, 20, 20);
pN->DrawTextCheckmark();
pR->AddBBox(0, 0, 20, 20);
pR->DrawTextCheckmark();
break;
}
case 2:
{
pN->AddBBox(0, 0, 20, 20);
pN->DrawTextCircle(sColor);
pR->AddBBox(0, 0, 20, 20);
pR->DrawTextCircle(sColor);
break;
}
case 3:
{
pN->AddBBox(0, 0, 24, 24);
pN->DrawTextCommentN(sColor);
pR->AddBBox(0, 0, 24, 24);
pR->DrawTextCommentR(sColor);
break;
}
case 4:
{
pN->AddBBox(0, 0, 19, 19);
pN->DrawTextCross(sColor);
pR->AddBBox(0, 0, 19, 19);
pR->DrawTextCross(sColor);
break;
}
case 5:
{
pN->AddBBox(0, 0, 20, 20);
pN->DrawTextCrossHairs(sColor);
pR->AddBBox(0, 0, 20, 20);
pR->DrawTextCrossHairs(sColor);
break;
}
case 6:
{
pN->AddBBox(0, 0, 20, 20);
pN->DrawTextHelp(sColor);
pR->AddBBox(0, 0, 20, 20);
pR->DrawTextHelp(sColor);
break;
}
case 7:
{
pN->AddBBox(0, 0, 17, 20);
pN->DrawTextInsert(sColor);
pR->AddBBox(0, 0, 17, 20);
pR->DrawTextInsert(sColor);
break;
}
case 8:
{
pN->AddBBox(0, 0, 13, 18);
pN->DrawTextKey(sColor);
pR->AddBBox(0, 0, 13, 18);
pR->DrawTextKey(sColor);
break;
}
case 9:
{
pN->AddBBox(0, 0, 13, 20);
pN->DrawTextNewParagraph(sColor);
pR->AddBBox(0, 0, 13, 20);
pR->DrawTextNewParagraph(sColor);
break;
}
case 11:
{
pN->AddBBox(0, 0, 20, 20);
pN->DrawTextParagraph(sColor);
pR->AddBBox(0, 0, 20, 20);
pR->DrawTextParagraph(sColor);
break;
}
case 12:
{
pN->AddBBox(0, 0, 20, 20);
pN->DrawTextRightArrow(sColor);
pR->AddBBox(0, 0, 20, 20);
pR->DrawTextRightArrow(sColor);
break;
}
case 13:
{
pN->AddBBox(0, 0, 20, 17);
pN->DrawTextRightPointer(sColor);
pR->AddBBox(0, 0, 20, 17);
pR->DrawTextRightPointer(sColor);
break;
}
case 14:
{
pN->AddBBox(0, 0, 20, 19);
pN->DrawTextStar(sColor);
pR->AddBBox(0, 0, 20, 19);
pR->DrawTextStar(sColor);
break;
}
case 15:
{
pN->AddBBox(0, 0, 17, 20);
pN->DrawTextUpArrow(sColor);
pR->AddBBox(0, 0, 17, 20);
pR->DrawTextUpArrow(sColor);
break;
}
case 16:
{
pN->AddBBox(0, 0, 17, 17);
pN->DrawTextUpLeftArrow(sColor);
pR->AddBBox(0, 0, 17, 17);
pR->DrawTextUpLeftArrow(sColor);
break;
}
case 10:
default:
{
pN->AddBBox(0, 0, 18, 20);
pN->DrawTextNote(sColor);
pR->AddBBox(0, 0, 18, 20);
pR->DrawTextNote(sColor);
break;
}
}
}
//----------------------------------------------------------------------------------------
// CUriLinkAnnotation
//----------------------------------------------------------------------------------------
CUriLinkAnnotation::CUriLinkAnnotation(CXref* pXref, const char* sUri) : CAnnotation(pXref, AnnotLink)
{
CDictObject* pAction = new CDictObject();
if (!pAction)
return;
Add("A", pAction);
pAction->Add("Type", "Action");
pAction->Add("S", "URI");
pAction->Add("URI", new CStringObject(sUri));
}
//----------------------------------------------------------------------------------------
// CInkAnnotation
//----------------------------------------------------------------------------------------
CInkAnnotation::CInkAnnotation(CXref* pXref) : CMarkupAnnotation(pXref, AnnotInk)
{
}
void CInkAnnotation::SetInkList(const std::vector< std::vector<double> >& arrInkList)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("InkList", pArray);
for (const std::vector<double>& arrInk : arrInkList)
{
CArrayObject* pArrayI = new CArrayObject();
pArray->Add(pArrayI);
for (int i = 0; i < arrInk.size(); ++i)
pArrayI->Add(i % 2 == 0 ? (arrInk[i] + m_dPageX) : (m_dPageH - arrInk[i]));
}
}
//----------------------------------------------------------------------------------------
// CLineAnnotation
//----------------------------------------------------------------------------------------
CLineAnnotation::CLineAnnotation(CXref* pXref) : CMarkupAnnotation(pXref, AnnotLine), dL{0.0, 0.0, 0.0, 0.0}
{
m_nLE1 = ELineEndType::None;
m_nLE2 = ELineEndType::None;
}
void CLineAnnotation::SetCap(bool bCap)
{
Add("Open", new CBoolObject(bCap));
}
void CLineAnnotation::SetIT(BYTE nIT)
{
std::string sValue;
ELineIntentType eIT = ELineIntentType(nIT);
switch (eIT)
{
case ELineIntentType::LineDimension: sValue = "LineDimension"; break;
case ELineIntentType::LineArrow: sValue = "LineArrow"; break;
default: return;
}
Add("IT", sValue.c_str());
}
void CLineAnnotation::SetCP(BYTE nCP)
{
if (!Get("Open"))
return;
std::string sValue;
ECaptionPositioning eCP = ECaptionPositioning(nCP);
switch (eCP)
{
case ECaptionPositioning::Inline: sValue = "Inline"; break;
case ECaptionPositioning::Top: sValue = "Top"; break;
default: return;
}
Add("CP", sValue.c_str());
}
void CLineAnnotation::SetLL(const double& dLL)
{
Add("LL", dLL);
}
void CLineAnnotation::SetLLE(const double& dLLE)
{
Add("LLE", dLLE);
}
void CLineAnnotation::SetLLO(const double& dLLO)
{
Add("LLO", dLLO);
}
void CLineAnnotation::SetLE(BYTE nLE1, BYTE nLE2)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("LE", pArray);
pArray->Add(AddLE(nLE1).c_str());
pArray->Add(AddLE(nLE2).c_str());
m_nLE1 = ELineEndType(nLE1);
m_nLE2 = ELineEndType(nLE2);
}
void CLineAnnotation::SetL(const double& dL1, const double& dL2, const double& dL3, const double& dL4)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("L", pArray);
dL[0] = dL1 + m_dPageX;
dL[1] = m_dPageH - dL2;
dL[2] = dL3 + m_dPageX;
dL[3] = m_dPageH - dL4;
pArray->Add(dL[0]);
pArray->Add(dL[1]);
pArray->Add(dL[2]);
pArray->Add(dL[3]);
}
void CLineAnnotation::SetCO(const double& dCO1, const double& dCO2)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("CO", pArray);
pArray->Add(dCO1);
pArray->Add(dCO2);
}
void CLineAnnotation::SetIC(const std::vector<double>& arrIC)
{
AddToVectorD(this, "IC", arrIC);
}
void CLineAnnotation::SetAP()
{
CAnnotAppearance* pAppearance = new CAnnotAppearance(m_pXref, this);
Add("AP", pAppearance);
CAnnotAppearanceObject* pNormal = pAppearance->GetNormal();
pNormal->DrawLine();
}
//----------------------------------------------------------------------------------------
// CPopupAnnotation
//----------------------------------------------------------------------------------------
CPopupAnnotation::CPopupAnnotation(CXref* pXref) : CAnnotation(pXref, AnnotPopup)
{
}
void CPopupAnnotation::SetOpen(bool bOpen)
{
Add("Open", new CBoolObject(bOpen));
}
void CPopupAnnotation::SetParentID(CAnnotation* pAnnot)
{
Add("Parent", pAnnot);
}
//----------------------------------------------------------------------------------------
// CFreeTextAnnotation
//----------------------------------------------------------------------------------------
CFreeTextAnnotation::CFreeTextAnnotation(CXref* pXref) : CMarkupAnnotation(pXref, AnnotFreeText)
{
}
void CFreeTextAnnotation::SetDA(CFontDict* pFont, const double& dFontSize, const std::vector<double>& arrC)
{
if (!pFont)
return;
CResourcesDict* pFieldsResources = m_pDocument->GetFieldsResources();
const char* sFontName = pFieldsResources->GetFontName(pFont);
std::vector<double> _arrC = arrC;
if (arrC.empty())
_arrC = {0};
std::string sDA = GetColor(_arrC, false);
if (sFontName)
{
sDA.append(" /");
sDA.append(sFontName);
sDA.append(" ");
sDA.append(std::to_string(dFontSize));
sDA.append(" Tf");
}
Add("DA", new CStringObject(sDA.c_str()));
}
void CFreeTextAnnotation::SetQ(BYTE nQ)
{
Add("Q", (int)nQ);
}
void CFreeTextAnnotation::SetIT(BYTE nIT)
{
std::string sValue;
switch (nIT)
{
case 0:
{ sValue = "FreeText"; break; }
case 1:
{ sValue = "FreeTextCallout"; break; }
case 2:
{ sValue = "FreeTextTypeWriter"; break; }
default: { return; }
}
Add("IT", sValue.c_str());
}
void CFreeTextAnnotation::SetLE(BYTE nLE)
{
Add("LE", AddLE(nLE).c_str());
}
void CFreeTextAnnotation::SetRotate(int nRotate)
{
Add("Rotate", nRotate);
}
void CFreeTextAnnotation::SetDS(const std::wstring& wsDS)
{
std::string sValue = U_TO_UTF8(wsDS);
Add("DS", new CStringObject(sValue.c_str()));
}
void CFreeTextAnnotation::SetRD(const double& dRD1, const double& dRD2, const double& dRD3, const double& dRD4)
{
AddRD(this, dRD1, dRD2, dRD3, dRD4);
}
void CFreeTextAnnotation::SetCL(const std::vector<double>& arrCL)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("CL", pArray);
for (int i = 0; i < arrCL.size(); ++i)
pArray->Add(i % 2 == 0 ? (arrCL[i] + m_dPageX) : (m_dPageH - arrCL[i]));
}
void CFreeTextAnnotation::SetIC(const std::vector<double>& arrIC)
{
SetC(arrIC);
}
//----------------------------------------------------------------------------------------
// CTextMarkupAnnotation
//----------------------------------------------------------------------------------------
CTextMarkupAnnotation::CTextMarkupAnnotation(CXref* pXref) : CMarkupAnnotation(pXref, AnnotHighLight)
{
m_nSubtype = AnnotHighLight;
}
void CTextMarkupAnnotation::SetSubtype(BYTE nSubtype)
{
switch (nSubtype)
{
case 8:
{ m_nSubtype = AnnotHighLight; break; }
case 9:
{ m_nSubtype = AnnotUnderline; break; }
case 10:
{ m_nSubtype = AnnotSquiggly; break; }
default:
case 11:
{ m_nSubtype = AnnotStrikeOut; break; }
}
Add("Subtype", c_sAnnotTypeNames[(int)m_nSubtype]);
}
void CTextMarkupAnnotation::SetQuadPoints(const std::vector<double>& arrQuadPoints)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("QuadPoints", pArray);
for (int i = 0; i < arrQuadPoints.size(); ++i)
pArray->Add(i % 2 == 0 ? (arrQuadPoints[i] + m_dPageX) : (m_dPageH - arrQuadPoints[i]));
}
void CTextMarkupAnnotation::SetAP(const std::vector<double>& arrQuadPoints, const double& dCA)
{
CAnnotAppearance* pAP = new CAnnotAppearance(m_pXref, this);
Add("AP", pAP);
CResourcesDict* pResources = new CResourcesDict(m_pXref, true, false);
CAnnotAppearanceObject* pN = pAP->GetNormal(pResources);
CStream* pStream = pN->GetStream();
pN->AddBBox(GetRect().fLeft, GetRect().fBottom, GetRect().fRight, GetRect().fTop);
pN->AddMatrix(1, 0, 0, 1, -GetRect().fLeft, -GetRect().fBottom);
CExtGrState* pExtGrState = m_pDocument->GetExtGState(dCA, dCA, m_nSubtype == AnnotHighLight ? blendmode_Multiply : blendmode_Unknown);
const char* sExtGrStateName = pResources->GetExtGrStateName(pExtGrState);
if (sExtGrStateName)
{
pStream->WriteEscapeName(sExtGrStateName);
pStream->WriteStr(" gs\012");
}
std::string sColor = GetColor(dynamic_cast<CArrayObject*>(Get("C")), m_nSubtype != AnnotHighLight);
pStream->WriteStr(sColor.c_str());
pStream->WriteChar('\012');
switch (m_nSubtype)
{
case AnnotHighLight:
{
pStream->WriteStr("1 w\012");
for (int i = 0; i < arrQuadPoints.size(); i += 8)
{
pStream->WriteReal(arrQuadPoints[i] + m_dPageX);
pStream->WriteChar(' ');
pStream->WriteReal(m_dPageH - arrQuadPoints[i + 1]);
pStream->WriteStr(" m\012");
pStream->WriteReal(arrQuadPoints[i + 2] + m_dPageX);
pStream->WriteChar(' ');
pStream->WriteReal(m_dPageH - arrQuadPoints[i + 3]);
pStream->WriteStr(" l\012");
pStream->WriteReal(arrQuadPoints[i + 6] + m_dPageX);
pStream->WriteChar(' ');
pStream->WriteReal(m_dPageH - arrQuadPoints[i + 7]);
pStream->WriteStr(" l\012");
pStream->WriteReal(arrQuadPoints[i + 4] + m_dPageX);
pStream->WriteChar(' ');
pStream->WriteReal(m_dPageH - arrQuadPoints[i + 5]);
pStream->WriteStr(" l\012f\012");
}
break;
}
case AnnotSquiggly:
case AnnotUnderline:
{
for (int i = 0; i < arrQuadPoints.size(); i += 8)
{
double dX = arrQuadPoints[i + 2] - arrQuadPoints[i];
double dY = arrQuadPoints[i + 3] - arrQuadPoints[i + 1];
double dAngle = atan2(dY, dX);
double dHeight = sqrt(pow(arrQuadPoints[i] - arrQuadPoints[i + 4], 2) + pow(arrQuadPoints[i + 1] - arrQuadPoints[i + 5], 2));
double dLineWidth = std::max(0.5, dHeight * 0.075);
double dIndentX = sin(dAngle) * dLineWidth * 1.9;
double dIndentY = cos(dAngle) * dLineWidth * 1.9;
pStream->WriteReal(dLineWidth);
pStream->WriteStr(" w\012");
pStream->WriteReal(arrQuadPoints[i + 4] + m_dPageX + dIndentX);
pStream->WriteChar(' ');
pStream->WriteReal(m_dPageH - arrQuadPoints[i + 5] + dIndentY);
pStream->WriteStr(" m\012");
pStream->WriteReal(arrQuadPoints[i + 6] + m_dPageX + dIndentX);
pStream->WriteChar(' ');
pStream->WriteReal(m_dPageH - arrQuadPoints[i + 7] + dIndentY);
pStream->WriteStr(" l\012S\012");
}
break;
}
case AnnotStrikeOut:
default:
{
for (int i = 0; i < arrQuadPoints.size(); i += 8)
{
double dX1 = arrQuadPoints[i] + (arrQuadPoints[i + 4] - arrQuadPoints[i]) / 2.0;
double dY1 = arrQuadPoints[i + 1] + (arrQuadPoints[i + 5] - arrQuadPoints[i + 1]) / 2.0;
double dX2 = arrQuadPoints[i + 2] + (arrQuadPoints[i + 6] - arrQuadPoints[i + 2]) / 2.0;
double dY2 = arrQuadPoints[i + 3] + (arrQuadPoints[i + 7] - arrQuadPoints[i + 3]) / 2.0;
double dHeight = sqrt(pow(arrQuadPoints[i] - arrQuadPoints[i + 4], 2) + pow(arrQuadPoints[i + 1] - arrQuadPoints[i + 5], 2));
double dLineWidth = std::max(0.5, dHeight * 0.075);
pStream->WriteReal(dLineWidth);
pStream->WriteStr(" w\012");
pStream->WriteReal(dX1 + m_dPageX);
pStream->WriteChar(' ');
pStream->WriteReal(m_dPageH - dY1);
pStream->WriteStr(" m\012");
pStream->WriteReal(dX2 + m_dPageX);
pStream->WriteChar(' ');
pStream->WriteReal(m_dPageH - dY2);
pStream->WriteStr(" l\012S\012");
}
break;
}
}
}
//----------------------------------------------------------------------------------------
// CSquareCircleAnnotation
//----------------------------------------------------------------------------------------
CSquareCircleAnnotation::CSquareCircleAnnotation(CXref* pXref) : CMarkupAnnotation(pXref, AnnotSquare)
{
m_nSubtype = AnnotSquare;
}
void CSquareCircleAnnotation::SetSubtype(BYTE nSubtype)
{
switch (nSubtype)
{
case 4:
{ m_nSubtype = AnnotSquare; break; }
default:
case 5:
{ m_nSubtype = AnnotCircle; break; }
}
Add("Subtype", c_sAnnotTypeNames[(int)m_nSubtype]);
}
void CSquareCircleAnnotation::SetRD(const double& dRD1, const double& dRD2, const double& dRD3, const double& dRD4)
{
AddRD(this, dRD1, dRD2, dRD3, dRD4);
}
void CSquareCircleAnnotation::SetIC(const std::vector<double>& arrIC)
{
AddToVectorD(this, "IC", arrIC);
}
//----------------------------------------------------------------------------------------
// CPolygonLineAnnotation
//----------------------------------------------------------------------------------------
CPolygonLineAnnotation::CPolygonLineAnnotation(CXref* pXref) : CMarkupAnnotation(pXref, AnnotPolygon)
{
m_nSubtype = AnnotPolygon;
}
void CPolygonLineAnnotation::SetIT(BYTE nIT)
{
std::string sValue;
switch (nIT)
{
case 0:
{ sValue = "PolygonCloud"; break; }
case 1:
{ sValue = "PolyLineDimension"; break; }
case 2:
{ sValue = "PolygonDimension"; break; }
default: { return; }
}
Add("IT", sValue.c_str());
}
void CPolygonLineAnnotation::SetSubtype(BYTE nSubtype)
{
switch (nSubtype)
{
case 6:
{ m_nSubtype = AnnotPolygon; break; }
default:
case 7:
{ m_nSubtype = AnnotPolyLine; break; }
}
Add("Subtype", c_sAnnotTypeNames[(int)m_nSubtype]);
}
void CPolygonLineAnnotation::SetLE(BYTE nLE1, BYTE nLE2)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("LE", pArray);
pArray->Add(AddLE(nLE1).c_str());
pArray->Add(AddLE(nLE2).c_str());
}
void CPolygonLineAnnotation::SetIC(const std::vector<double>& arrIC)
{
AddToVectorD(this, "IC", arrIC);
}
void CPolygonLineAnnotation::SetVertices(const std::vector<double>& arrVertices)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("Vertices", pArray);
for (int i = 0; i < arrVertices.size(); ++i)
pArray->Add(i % 2 == 0 ? (arrVertices[i] + m_dPageX) : (m_dPageH - arrVertices[i]));
}
//----------------------------------------------------------------------------------------
// CCaretAnnotation
//----------------------------------------------------------------------------------------
CCaretAnnotation::CCaretAnnotation(CXref* pXref) : CMarkupAnnotation(pXref, AnnotCaret)
{
}
void CCaretAnnotation::SetRD(const double& dRD1, const double& dRD2, const double& dRD3, const double& dRD4)
{
AddRD(this, dRD1, dRD2, dRD3, dRD4);
}
void CCaretAnnotation::SetSy(BYTE nSy)
{
std::string sValue;
switch (nSy)
{
case 0:
{ sValue = "P"; break; }
case 1:
{ sValue = "None"; break; }
default: { return; }
}
Add("IT", sValue.c_str());
}
//----------------------------------------------------------------------------------------
// CStampAnnotation
//----------------------------------------------------------------------------------------
CStampAnnotation::CStampAnnotation(CXref* pXref) : CMarkupAnnotation(pXref, AnnotStamp), m_pAPStream(NULL)
{
}
void CStampAnnotation::SetRotate(double nRotate)
{
Add("Rotate", nRotate);
if (!m_pAPStream)
return;
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
double ca = cos(nRotate / 180.0 * M_PI);
double sa = sin(nRotate / 180.0 * M_PI);
m_pAPStream->Add("Matrix", pArray);
pArray->Add(ca);
pArray->Add(sa);
pArray->Add(-sa);
pArray->Add(ca);
pArray->Add(0);
pArray->Add(0);
}
void CStampAnnotation::SetName(const std::wstring& wsName)
{
std::string sValue = U_TO_UTF8(wsName);
Add("Name", sValue.c_str());
}
void CStampAnnotation::SetAPStream(CDictObject* pStream, bool bCopy)
{
if (bCopy)
{
CDictObject* pStreamNew = (CDictObject*)pStream->Copy();
CStream* pStr = new CMemoryStream();
pStreamNew->SetStream(m_pXref, pStr, true);
pStr->WriteStream(pStream->GetStream(), 0, NULL);
pStreamNew->SetFilter(STREAM_FILTER_FLATE_DECODE);
pStream = pStreamNew;
CDictObject* pAP = new PdfWriter::CDictObject();
Add("AP", pAP);
pAP->Add("N", pStreamNew);
}
m_pAPStream = pStream;
}
CDictObject* CStampAnnotation::GetAPStream()
{
return m_pAPStream;
}
//----------------------------------------------------------------------------------------
// CRedactAnnotation
//----------------------------------------------------------------------------------------
CRedactAnnotation::CRedactAnnotation(CXref* pXref) : CMarkupAnnotation(pXref, AnnotRedact)
{
}
void CRedactAnnotation::SetDA(CFontDict* pFont, const double& dFontSize, const std::vector<double>& arrC)
{
const char* sFontName = NULL;
if (pFont)
{
CResourcesDict* pFieldsResources = m_pDocument->GetFieldsResources();
sFontName = pFieldsResources->GetFontName(pFont);
}
std::vector<double> _arrC = arrC;
if (arrC.empty())
_arrC = {0};
std::string sDA = GetColor(_arrC, false);
if (sFontName)
{
sDA.append(" /");
sDA.append(sFontName);
sDA.append(" ");
sDA.append(std::to_string(dFontSize));
sDA.append(" Tf");
}
Add("DA", new CStringObject(sDA.c_str()));
}
void CRedactAnnotation::SetRepeat(bool bRepeat)
{
Add("Repeat", bRepeat);
}
void CRedactAnnotation::SetQ(BYTE nQ)
{
Add("Q", (int)nQ);
}
void CRedactAnnotation::SetOverlayText(const std::wstring& wsOverlayText)
{
std::string sValue = U_TO_UTF8(wsOverlayText);
Add("OverlayText", new CStringObject(sValue.c_str(), true));
}
void CRedactAnnotation::SetIC(const std::vector<double>& arrIC)
{
AddToVectorD(this, "IC", arrIC);
}
void CRedactAnnotation::SetOC(const std::vector<double>& arrOC)
{
AddToVectorD(this, "OC", arrOC);
}
void CRedactAnnotation::SetQuadPoints(const std::vector<double>& arrQuadPoints)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("QuadPoints", pArray);
for (int i = 0; i < arrQuadPoints.size(); ++i)
pArray->Add(i % 2 == 0 ? (arrQuadPoints[i] + m_dPageX) : (m_dPageH - arrQuadPoints[i]));
}
//----------------------------------------------------------------------------------------
// CWidgetAnnotation
//----------------------------------------------------------------------------------------
CWidgetAnnotation::CWidgetAnnotation(CXref* pXref, EAnnotType eType) : CAnnotation(pXref, eType)
{
m_pMK = NULL;
m_pParent = NULL;
m_pAppearance = NULL;
m_pResources = NULL;
m_pFont = NULL;
m_dFontSizeAP = 0;
m_nParentID = 0;
m_nQ = 0;
m_dFontSize = 10.0;
m_bBold = false;
m_bItalic = false;
m_nSubtype = WidgetUnknown;
}
void CWidgetAnnotation::SetSubtype(BYTE nSubtype)
{
m_nSubtype = (EWidgetType)nSubtype;
}
void CWidgetAnnotation::SetDA(CFontDict* pFont, const double& dFontSize, const double& dFontSizeAP, const std::vector<double>& arrTC)
{
if (!pFont)
return;
CResourcesDict* pFieldsResources = m_pDocument->GetFieldsResources();
const char* sFontName = pFieldsResources->GetFontName(pFont);
std::string sDA = GetColor(arrTC, false);
if (sFontName)
{
sDA.append(" /");
sDA.append(sFontName);
sDA.append(" ");
sDA.append(std::to_string(dFontSize));
sDA.append(" Tf");
}
CDictObject* pOwner = GetObjOwnValue("DA");
if (pOwner)
pOwner->Remove("DA");
Add("DA", new CStringObject(sDA.c_str()));
m_arrTC = arrTC;
m_dFontSizeAP = dFontSizeAP;
}
void CWidgetAnnotation::SetFont(CFontCidTrueType* pFont, double dFontSize, bool bBold, bool bItalic)
{
m_pFont = pFont;
m_dFontSize = dFontSize;
m_bBold = bBold;
m_bItalic = bItalic;
}
CDictObject* CWidgetAnnotation::GetObjOwnValue(const std::string& sV)
{
if (Get(sV))
return this;
CDictObject* pParent = m_pParent;
while (pParent)
{
if (pParent->Get(sV))
return pParent;
CObjectBase* pParent2 = pParent->Get("Parent");
if (pParent2 && pParent2->GetType() == object_type_DICT)
pParent = (CDictObject*)pParent2;
else
return NULL;
}
return NULL;
}
CObjectBase* CWidgetAnnotation::GetObjValue(const std::string& sV)
{
CObjectBase* pRes = Get(sV);
if (pRes)
return pRes;
CDictObject* pParent = m_pParent;
while (pParent)
{
pRes = pParent->Get(sV);
if (pRes)
return pRes;
CObjectBase* pParent2 = pParent->Get("Parent");
if (pParent2 && pParent2->GetType() == object_type_DICT)
pParent = (CDictObject*)pParent2;
else
return NULL;
}
return NULL;
}
void CWidgetAnnotation::CheckMK()
{
if (!m_pMK)
{
CObjectBase* pMK = Get("MK");
if (pMK && pMK->GetType() == object_type_DICT)
{
m_pMK = (CDictObject*)pMK;
return;
}
m_pMK = new CDictObject();
Add("MK", m_pMK);
}
}
void CWidgetAnnotation::SetQ(BYTE nQ)
{
CDictObject* pOwner = GetObjOwnValue("Q");
if (!pOwner)
pOwner = this;
pOwner->Add("Q", (int)nQ);
m_nQ = nQ;
}
void CWidgetAnnotation::SetH(BYTE nH)
{
std::string sValue;
switch (nH)
{
case 0:
{ sValue = "N"; break; }
case 1:
{ sValue = "I"; break; }
case 2:
{ sValue = "P"; break; }
case 3:
{ sValue = "O"; break; }
default: { return; }
}
Add("H", sValue.c_str());
}
void CWidgetAnnotation::SetR(const int& nR)
{
CheckMK();
m_pMK->Add("R", nR);
}
void CWidgetAnnotation::SetFlag(const int& nFlag)
{
if (nFlag < 0)
return;
CDictObject* pOwner = GetObjOwnValue("Ff");
if (!pOwner)
pOwner = this;
pOwner->Add("Ff", nFlag);
}
void CWidgetAnnotation::SetParent(CDictObject* pParent)
{
if (!pParent)
return;
m_pParent = pParent;
Add("Parent", pParent);
}
void CWidgetAnnotation::SetParentID(int nParentID)
{
m_nParentID = nParentID;
}
void CWidgetAnnotation::SetMEOptions(const int& nMEOptions)
{
Add("MEOptions", nMEOptions);
}
void CWidgetAnnotation::SetTU(const std::wstring& wsTU)
{
std::string sValue = U_TO_UTF8(wsTU);
CDictObject* pOwner = GetObjOwnValue("TU");
if (!pOwner)
pOwner = this;
pOwner->Add("TU", new CStringObject(sValue.c_str(), true));
}
void CWidgetAnnotation::SetDS(const std::wstring& wsDS)
{
std::string sValue = U_TO_UTF8(wsDS);
CDictObject* pOwner = GetObjOwnValue("DS");
if (!pOwner)
pOwner = this;
pOwner->Add("DS", new CStringObject(sValue.c_str(), true));
}
void CWidgetAnnotation::SetDV(const std::wstring& wsDV)
{
std::string sValue = U_TO_UTF8(wsDV);
CDictObject* pOwner = GetObjOwnValue("DV");
if (!pOwner)
pOwner = this;
pOwner->Add("DV", new CStringObject(sValue.c_str(), true));
}
void CWidgetAnnotation::SetT(const std::wstring& wsT)
{
std::string sValue = U_TO_UTF8(wsT);
CDictObject* pOwner = GetObjOwnValue("T");
if (!pOwner)
pOwner = this;
pOwner->Add("T", new CStringObject(sValue.c_str(), true));
}
void CWidgetAnnotation::SetBC(const std::vector<double>& arrBC)
{
CheckMK();
AddToVectorD(m_pMK, "BC", arrBC);
}
void CWidgetAnnotation::SetBG(const std::vector<double>& arrBG)
{
CheckMK();
AddToVectorD(m_pMK, "BG", arrBG);
}
void CWidgetAnnotation::AddAction(CAction* pAction)
{
if (!pAction)
return;
if (pAction->m_sType == "A")
{
Add(pAction->m_sType.c_str(), pAction);
return;
}
CDictObject* pAA = (CDictObject*)Get("AA");
if (!pAA)
{
pAA = new CDictObject();
Add("AA", pAA);
}
pAA->Add(pAction->m_sType.c_str(), pAction);
}
void CWidgetAnnotation::SetDocument(CDocument* pDocument)
{
m_pDocument = pDocument;
m_pResources = m_pDocument->GetFieldsResources();
}
std::string CWidgetAnnotation::GetDAforAP(CFontDict* pFont)
{
const char* sFontName = m_pResources->GetFontName(pFont);
std::string sDA = GetColor(m_arrTC, false);
if (sFontName)
{
sDA.append(" /");
sDA.append(sFontName);
sDA.append(" ");
sDA.append(std::to_string(m_dFontSizeAP));
sDA.append(" Tf\012");
}
return sDA;
}
std::string CWidgetAnnotation::GetBGforAP(double dDiff, bool bCAPS)
{
if (m_pMK)
return GetColor(dynamic_cast<CArrayObject*>(m_pMK->Get("BG")), bCAPS, dDiff);
return "";
}
std::string CWidgetAnnotation::GetBCforAP()
{
if (m_pMK)
return GetColor(dynamic_cast<CArrayObject*>(m_pMK->Get("BC")), true);
return "";
}
int CWidgetAnnotation::GetR()
{
if (m_pMK)
{
CObjectBase* pObj = m_pMK->Get("R");
if (pObj && pObj->GetType() == object_type_NUMBER)
return ((CNumberObject*)pObj)->Get();
}
return 0;
}
bool CWidgetAnnotation::HaveBG()
{
if (!m_pMK)
return false;
CObjectBase* pObj = m_pMK->Get("BG");
return pObj && pObj->GetType() == object_type_ARRAY;
}
bool CWidgetAnnotation::HaveBC()
{
if (!m_pMK)
return false;
CObjectBase* pObj = m_pMK->Get("BC");
return pObj && pObj->GetType() == object_type_ARRAY;
}
void CWidgetAnnotation::SetEmptyAP()
{
if (!m_pAppearance)
m_pAppearance = new CAnnotAppearance(m_pXref, this);
Add("AP", m_pAppearance);
CAnnotAppearanceObject* pAppearance = m_pAppearance->GetNormal();
double dHeight = fabs(m_oRect.fTop - m_oRect.fBottom);
double dWidth = fabs(m_oRect.fRight - m_oRect.fLeft);
pAppearance->StartDraw(dWidth, dHeight);
pAppearance->EndDraw();
}
void CWidgetAnnotation::SetAP(const std::wstring& wsValue, unsigned short* pCodes, unsigned int unCount, double dX, double dY, CFontCidTrueType** ppFonts, double* pShifts)
{
if (!m_pAppearance)
m_pAppearance = new CAnnotAppearance(m_pXref, this);
Add("AP", m_pAppearance);
CAnnotAppearanceObject* pNormal = m_pAppearance->GetNormal();
pNormal->DrawSimpleText(wsValue, pCodes, unCount, m_pFont, m_dFontSize, dX, dY, 0, 0, 0, NULL, fabs(m_oRect.fRight - m_oRect.fLeft), fabs(m_oRect.fBottom - m_oRect.fTop), ppFonts, pShifts);
}
CAnnotAppearanceObject* CWidgetAnnotation::StartAP(int nRotate)
{
CAnnotAppearanceObject* pNormal = CAnnotation::StartAP(nRotate);
m_pResources = dynamic_cast<CResourcesDict*>(pNormal->Get("Resources"));
double dW = fabs(m_oRect.fRight - m_oRect.fLeft);
double dH = fabs(m_oRect.fBottom - m_oRect.fTop);
if (nRotate == 0 || nRotate == 180)
pNormal->StartDrawText(m_pFont, m_dFontSize, 0, 0, 0, NULL, dW, dH);
else
pNormal->StartDrawText(m_pFont, m_dFontSize, 0, 0, 0, NULL, dH, dW);
pNormal->EndText();
if (nRotate == 0)
{
pNormal->AddBBox(0, 0, dW, dH);
pNormal->AddMatrix(1, 0, 0, 1, 0, 0);
}
if (nRotate == 90)
{
pNormal->AddBBox(0, 0, dH, dW);
pNormal->AddMatrix(0, 1, -1, 0, dW, 0);
}
else if (nRotate == 180)
{
pNormal->AddBBox(0, 0, dW, dH);
pNormal->AddMatrix(-1, 0, 0, -1, dW, dH);
}
else if (nRotate == 270)
{
pNormal->AddBBox(0, 0, dH, dW);
pNormal->AddMatrix(0, -1, 1, 0, 0, dH);
}
return pNormal;
}
void CWidgetAnnotation::AddLineToAP(const double& dX, const double& dY, unsigned short* pCodes, const unsigned int& unCodesCount, CFontCidTrueType** ppFonts, const double* pShifts)
{
if (!m_pAppearance)
return;
CAnnotAppearanceObject* pNormal = m_pAppearance->GetNormal();
pNormal->DrawTextLine(dX, dY, pCodes, unCodesCount, ppFonts, pShifts);
}
void CWidgetAnnotation::EndAP()
{
if (!m_pAppearance)
return;
CAnnotAppearanceObject* pNormal = m_pAppearance->GetNormal();
pNormal->EndDrawText();
}
//----------------------------------------------------------------------------------------
// CPushButtonWidget
//----------------------------------------------------------------------------------------
CPushButtonWidget::CPushButtonWidget(CXref* pXref) : CWidgetAnnotation(pXref, AnnotWidget)
{
m_pIF = NULL;
m_nI = -1;
m_nRI = -1;
m_nIX = -1;
m_nTP = 0;
m_nScaleType = 0;
m_bRespectBorders = false;
m_bConstantProportions = true;
m_dShiftX = 0.5;
m_dShiftY = 0.5;
}
void CPushButtonWidget::CheckIF()
{
CheckMK();
if (!m_pIF)
{
m_pIF = new CDictObject();
m_pMK->Add("IF", m_pIF);
}
}
void CPushButtonWidget::SetV(const std::wstring& wsV)
{
std::string sV = U_TO_UTF8(wsV);
CDictObject* pOwner = GetObjOwnValue("V");
if (!pOwner)
pOwner = this;
pOwner->Add("V", new CStringObject(sV.c_str(), true));
}
void CPushButtonWidget::SetS(BYTE nS)
{
m_bConstantProportions = !nS;
CheckIF();
std::string sValue;
switch (nS)
{
case 0:
{ sValue = "P"; break; }
case 1:
{ sValue = "A"; break; }
default: { return; }
}
m_pIF->Add("S", sValue.c_str());
}
void CPushButtonWidget::SetTP(BYTE nTP)
{
CheckMK();
m_pMK->Add("TP", (int)nTP);
m_nTP = nTP;
}
void CPushButtonWidget::SetSW(BYTE nSW)
{
m_nScaleType = nSW;
CheckIF();
std::string sValue;
switch (nSW)
{
case 0:
{ sValue = "A"; break; }
case 1:
{ sValue = "N"; break; }
case 2:
{ sValue = "B"; break; }
case 3:
{ sValue = "S"; break; }
default: { return; }
}
m_pIF->Add("SW", sValue.c_str());
}
void CPushButtonWidget::SetIFFlag(const int& nIFFlag)
{
CheckIF();
m_bRespectBorders = (nIFFlag & (1 << 4)) ? false : true;
m_pIF->Add("FB", !m_bRespectBorders);
}
void CPushButtonWidget::SetFlag(const int& nFlag)
{
if (nFlag < 0)
return;
int nFlags = nFlag;
nFlags |= (1 << 16);
CWidgetAnnotation::SetFlag(nFlags);
}
void CPushButtonWidget::SetI(const int& nI)
{
m_nI = nI;
}
void CPushButtonWidget::SetRI(const int& nRI)
{
m_nRI = nRI;
}
void CPushButtonWidget::SetIX(const int& nIX)
{
m_nIX = nIX;
}
void CPushButtonWidget::SetA(const double& dA1, const double& dA2)
{
m_dShiftX = dA1;
m_dShiftY = dA2;
CheckIF();
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
m_pIF->Add("A", pArray);
pArray->Add(dA1);
pArray->Add(dA2);
}
void CPushButtonWidget::SetCA(const std::wstring& wsCA)
{
CheckMK();
std::string sValue = U_TO_UTF8(wsCA);
m_pMK->Add("CA", new CStringObject(sValue.c_str(), true));
m_wsCA = wsCA;
}
void CPushButtonWidget::SetRC(const std::wstring& wsRC)
{
CheckMK();
std::string sValue = U_TO_UTF8(wsRC);
m_pMK->Add("RC", new CStringObject(sValue.c_str(), true));
m_wsRC = wsRC;
}
void CPushButtonWidget::SetAC(const std::wstring& wsAC)
{
CheckMK();
std::string sValue = U_TO_UTF8(wsAC);
m_pMK->Add("AC", new CStringObject(sValue.c_str(), true));
m_wsAC = wsAC;
}
void CPushButtonWidget::SetAP(CXObject* pForm, BYTE nAP, unsigned short* pCodes, unsigned int unCount, double dX, double dY, double dLineW, double dLineH, CFontCidTrueType** ppFonts, bool bNoAP)
{
if (!pForm && !pCodes)
{
CObjectBase* pAP = Get("AP");
if (pAP && pAP->GetType() == object_type_DICT)
{
CDictObject* pDAP = (CDictObject*)pAP;
std::string sAP = nAP == 0 ? "N" : (nAP == 1 ? "R" : "D");
pDAP->Remove(sAP);
}
if (m_pMK)
{
std::string sAP = nAP == 0 ? "I" : (nAP == 1 ? "RI" : "IX");
m_pMK->Remove(sAP);
}
if (nAP != 0)
return;
}
if (!m_pAppearance)
{
m_pAppearance = new CAnnotAppearance(m_pXref, this);
CObjectBase* pAP = Get("AP");
if (pAP && pAP->GetType() == object_type_DICT)
{
CDictObject* pDAP = (CDictObject*)pAP;
CObjectBase* pAPi = pDAP->Get("N");
if (pAPi)
{
CProxyObject* pNewAPi = new CProxyObject(pAPi->Copy(), true);
pNewAPi->Get()->SetRef(pAPi->GetObjId(), pAPi->GetGenNo());
m_pAppearance->Add("N", pNewAPi);
}
pAPi = pDAP->Get("D");
if (pAPi)
{
CProxyObject* pNewAPi = new CProxyObject(pAPi->Copy(), true);
pNewAPi->Get()->SetRef(pAPi->GetObjId(), pAPi->GetGenNo());
m_pAppearance->Add("D", pNewAPi);
}
pAPi = pDAP->Get("R");
if (pAPi)
{
CProxyObject* pNewAPi = new CProxyObject(pAPi->Copy(), true);
pNewAPi->Get()->SetRef(pAPi->GetObjId(), pAPi->GetGenNo());
m_pAppearance->Add("R", pNewAPi);
}
}
}
if (bNoAP)
{
if (pForm)
{
CheckMK();
std::string sAP = nAP == 0 ? "I" : (nAP == 1 ? "RI" : "IX");
m_pMK->Add(sAP, pForm);
}
else if (m_pMK)
{
std::string sAP = nAP == 0 ? "I" : (nAP == 1 ? "RI" : "IX");
m_pMK->Remove(sAP);
}
return;
}
CAnnotAppearanceObject* pAppearance = NULL;
m_pResources = new CResourcesDict(NULL, true, false);
if (nAP == 0)
pAppearance = m_pAppearance->GetNormal(m_pResources);
else if (nAP == 1)
pAppearance = m_pAppearance->GetRollover(m_pResources);
else if (nAP == 2)
pAppearance = m_pAppearance->GetDown(m_pResources);
else
{
delete m_pResources;
m_pResources = m_pDocument->GetFieldsResources();
}
if (!pAppearance)
return;
Add("AP", m_pAppearance);
double dHeight = fabs(m_oRect.fTop - m_oRect.fBottom);
double dWidth = fabs(m_oRect.fRight - m_oRect.fLeft);
int nRotate = GetR();
if (nRotate == 0)
{
pAppearance->AddBBox(0, 0, dWidth, dHeight);
pAppearance->AddMatrix(1, 0, 0, 1, 0, 0);
}
if (nRotate == 90)
{
pAppearance->AddBBox(0, 0, dHeight, dWidth);
pAppearance->AddMatrix(0, 1, -1, 0, dWidth, 0);
}
else if (nRotate == 180)
{
pAppearance->AddBBox(0, 0, dWidth, dHeight);
pAppearance->AddMatrix(-1, 0, 0, -1, dWidth, dHeight);
}
else if (nRotate == 270)
{
pAppearance->AddBBox(0, 0, dHeight, dWidth);
pAppearance->AddMatrix(0, -1, 1, 0, 0, dHeight);
}
if (nRotate == 90 || nRotate == 270)
std::swap(dWidth, dHeight);
pAppearance->StartDraw(dWidth, dHeight);
if (pForm)
{
double dH = dHeight;
double dW = dWidth;
double dOriginW = pForm->GetWidth();
double dOriginH = pForm->GetHeight();
bool bNeedScale = (0 == m_nScaleType
|| (2 == m_nScaleType && (dOriginH > dH || dOriginW > dW))
|| (3 == m_nScaleType && dOriginH < dH && dOriginW < dW));
double dBorderSize = m_oBorder.dWidth;
if (m_oBorder.nType == EBorderType::Beveled || m_oBorder.nType == EBorderType::Inset)
dBorderSize *= 2;
double dDstW = dOriginW;
double dDstH = dOriginH;
double dDstX = 0;
double dDstY = 0;
if (m_nTP == 2)
{
dH -= (dLineH + dBorderSize);
dDstY += (dLineH + dBorderSize);
}
if (m_nTP == 3)
dH -= (dLineH + dBorderSize);
if (m_nTP == 4)
dW -= (dLineW + dBorderSize);
if (m_nTP == 5)
{
dW -= (dLineW + dBorderSize);
dDstX += (dLineW + dBorderSize);
}
if (m_bRespectBorders)
{
dDstX += 2 * dBorderSize;
dDstY += 2 * dBorderSize;
dH -= 4 * dBorderSize;
dW -= 4 * dBorderSize;
}
if (bNeedScale)
{
if (!m_bConstantProportions)
{
dDstH = dH;
dDstW = dW;
}
else
{
double dScaleKoef = fmin(dW / dOriginW, dH / dOriginH);
dDstW = dScaleKoef * dOriginW;
dDstH = dScaleKoef * dOriginH;
}
}
dDstX += (dW - dDstW) * m_dShiftX;
dDstY += (dH - dDstH) * m_dShiftY;
m_pResources->AddXObjectWithName(pForm->GetName().c_str(), pForm);
pAppearance->DrawPictureInline(dWidth, dHeight, pForm->GetName().c_str(), dDstX, dDstY, dDstW / dOriginW, dDstH / dOriginH, m_bRespectBorders);
CheckMK();
std::string sAP = nAP == 0 ? "I" : (nAP == 1 ? "RI" : "IX");
m_pMK->Add(sAP, pForm);
}
else if (m_pMK)
{
std::string sAP = nAP == 0 ? "I" : (nAP == 1 ? "RI" : "IX");
m_pMK->Remove(sAP);
}
if (pCodes)
{
pAppearance->StartText(m_pFont, m_dFontSize);
pAppearance->DrawTextLine(dX, dY, pCodes, unCount, ppFonts, NULL);
pAppearance->EndText();
}
pAppearance->EndDraw();
}
//----------------------------------------------------------------------------------------
// CCheckBoxWidget
//----------------------------------------------------------------------------------------
CCheckBoxWidget::CCheckBoxWidget(CXref* pXref, EWidgetType nSubtype) : CWidgetAnnotation(pXref, AnnotWidget)
{
m_nSubtype = nSubtype;
m_nStyle = ECheckBoxStyle::Circle;
m_pAP = NULL;
}
void CCheckBoxWidget::SetV(const std::wstring& wsV)
{
std::string sV = U_TO_UTF8(wsV);
CDictObject* pOwner = GetObjOwnValue("V");
if (!pOwner)
pOwner = this;
if (isdigit(sV[0]))
pOwner->Add("V", sV.c_str());
else
pOwner->Add("V", new CStringObject(sV.c_str(), true));
}
void CCheckBoxWidget::SetStyle(BYTE nStyle)
{
m_nStyle = ECheckBoxStyle(nStyle);
CheckMK();
m_pMK->Add("CA", new CStringObject(c_sCheckBoxStyleNames[(int)nStyle]));
}
void CCheckBoxWidget::SetAP_N_Yes(const std::wstring& wsAP_N_Yes)
{
std::string sValue = U_TO_UTF8(wsAP_N_Yes);
if (m_sAP_N_Yes.empty())
m_sAP_N_Yes = sValue;
if (m_pAP)
{
CDictObject* pDict = (CDictObject*)m_pAP->Get("N");
pDict->Add(m_sAP_N_Yes, m_pAP->GetYesN());
pDict->Remove("Yes");
pDict = (CDictObject*)m_pAP->Get("D");
pDict->Add(m_sAP_N_Yes, m_pAP->GetYesD());
pDict->Remove("Yes");
}
}
void CCheckBoxWidget::RenameAP_N_Yes(const std::wstring& wsAP_N_Yes)
{
std::string sValue = U_TO_UTF8(wsAP_N_Yes);
m_sAP_N_Yes = sValue;
if (m_pAP)
{
CDictObject* pDict = (CDictObject*)m_pAP->Get("N");
pDict->Add(m_sAP_N_Yes, m_pAP->GetYesN());
pDict->Remove("Yes");
pDict = (CDictObject*)m_pAP->Get("D");
pDict->Add(m_sAP_N_Yes, m_pAP->GetYesD());
pDict->Remove("Yes");
}
else
{
CObjectBase* pAPN = NULL;
CObjectBase* pAP = Get("AP");
if (pAP->GetType() == object_type_DICT)
pAPN = ((CDictObject*)pAP)->Get("N");
if (pAPN && pAPN->GetType() == object_type_DICT)
{
CDictObject* pDictAPN = (CDictObject*)pAPN;
std::map<std::string, CObjectBase*> mDict = pDictAPN->GetDict();
for (std::pair<std::string, CObjectBase*> it : mDict)
{
if (it.first != "Off" && it.first != m_sAP_N_Yes)
{
CObjectBase* pObject = it.second;
pDictAPN->Add(m_sAP_N_Yes, pObject->Copy());
pDictAPN->Remove(it.first);
break;
}
}
}
pAPN = NULL;
if (pAP->GetType() == object_type_DICT)
pAPN = ((CDictObject*)pAP)->Get("D");
if (pAPN && pAPN->GetType() == object_type_DICT)
{
CDictObject* pDictAPN = (CDictObject*)pAPN;
std::map<std::string, CObjectBase*> mDict = pDictAPN->GetDict();
for (std::pair<std::string, CObjectBase*> it : mDict)
{
if (it.first != "Off" && it.first != m_sAP_N_Yes)
{
CObjectBase* pObject = it.second;
pDictAPN->Add(m_sAP_N_Yes, pObject->Copy());
pDictAPN->Remove(it.first);
break;
}
}
}
}
}
bool CCheckBoxWidget::NeedAP_N_Yes()
{
return m_sAP_N_Yes.empty();
}
void CCheckBoxWidget::SetAP(int nRotate)
{
if (!m_pAP)
{
m_pAP = new CCheckBoxAnnotAppearance(m_pXref, this, m_sAP_N_Yes.empty() ? NULL : m_sAP_N_Yes.c_str());
Add("AP", m_pAP);
}
if (m_nStyle == ECheckBoxStyle::Circle && m_nSubtype == WidgetRadiobutton)
{
m_pAP->GetYesN()->DrawCheckBoxCircle(nRotate, true, true);
m_pAP->GetOffN()->DrawCheckBoxCircle(nRotate, false, true);
m_pAP->GetYesD()->DrawCheckBoxCircle(nRotate, true, false);
m_pAP->GetOffD()->DrawCheckBoxCircle(nRotate, false, false);
}
else
{
m_pAP->GetYesN()->DrawCheckBoxSquare(nRotate, true, true);
m_pAP->GetOffN()->DrawCheckBoxSquare(nRotate, false, true);
m_pAP->GetYesD()->DrawCheckBoxSquare(nRotate, true, false);
m_pAP->GetOffD()->DrawCheckBoxSquare(nRotate, false, false);
}
if (nRotate != 0)
{
double dW = fabs(m_oRect.fRight - m_oRect.fLeft);
double dH = fabs(m_oRect.fBottom - m_oRect.fTop);
if (nRotate == 90 || nRotate == 270)
{
m_pAP->GetYesN()->AddBBox(0, 0, dH, dW);
m_pAP->GetOffN()->AddBBox(0, 0, dH, dW);
m_pAP->GetYesD()->AddBBox(0, 0, dH, dW);
m_pAP->GetOffD()->AddBBox(0, 0, dH, dW);
}
if (nRotate == 90)
{
m_pAP->GetYesN()->AddMatrix(0, 1, -1, 0, dW, 0);
m_pAP->GetOffN()->AddMatrix(0, 1, -1, 0, dW, 0);
m_pAP->GetYesD()->AddMatrix(0, 1, -1, 0, dW, 0);
m_pAP->GetOffD()->AddMatrix(0, 1, -1, 0, dW, 0);
}
if (nRotate == 180)
{
m_pAP->GetYesN()->AddMatrix(-1, 0, 0, -1, dW, dH);
m_pAP->GetOffN()->AddMatrix(-1, 0, 0, -1, dW, dH);
m_pAP->GetYesD()->AddMatrix(-1, 0, 0, -1, dW, dH);
m_pAP->GetOffD()->AddMatrix(-1, 0, 0, -1, dW, dH);
}
if (nRotate == 270)
{
m_pAP->GetYesN()->AddMatrix(0, -1, 1, 0, 0, dH);
m_pAP->GetOffN()->AddMatrix(0, -1, 1, 0, 0, dH);
m_pAP->GetYesD()->AddMatrix(0, -1, 1, 0, 0, dH);
m_pAP->GetOffD()->AddMatrix(0, -1, 1, 0, 0, dH);
}
}
}
std::string CCheckBoxWidget::Yes()
{
std::string sName = m_sAP_N_Yes.empty() ? "Yes" : m_sAP_N_Yes;
Add("AS", sName.c_str());
if (!m_nParentID)
Add("V", sName.c_str());
return sName;
}
void CCheckBoxWidget::Off()
{
Add("AS", "Off");
if (!m_nParentID)
Add("V", "Off");
}
void CCheckBoxWidget::SwitchAP(const std::string& sV, int nI)
{
CObjectBase* pAP, *pAPN;
Add("AS", "Off");
CObjectBase* pObj = GetObjValue("Opt");
if (!m_sAP_N_Yes.empty() && pObj && pObj->GetType() == object_type_ARRAY)
{
if (m_pAP)
{
CDictObject* pDict = (CDictObject*)m_pAP->Get("N");
pDict->Remove(m_sAP_N_Yes);
pDict = (CDictObject*)m_pAP->Get("D");
pDict->Remove(m_sAP_N_Yes);
}
CArrayObject* pArr = (CArrayObject*)pObj;
for (int i = 0; i < pArr->GetCount(); ++i)
{
pObj = pArr->Get(i);
if (pObj->GetType() == object_type_ARRAY && ((CArrayObject*)pObj)->GetCount() > 0)
pObj = ((CArrayObject*)pObj)->Get(0);
if (pObj->GetType() == object_type_STRING)
{
CStringObject* pStr = (CStringObject*)pObj;
const BYTE* pBinary = pStr->GetString();
if (pStr->GetLength() == m_sAP_N_Yes.length() && !StrCmp((const char*)pBinary, m_sAP_N_Yes.c_str()))
{
m_sAP_N_Yes = std::to_string(i);
SetV(UTF8_TO_U(m_sAP_N_Yes));
break;
}
}
}
Add("AS", m_sAP_N_Yes.c_str());
if (nI >= 0 && m_pAP)
{
CDictObject* pDict = (CDictObject*)m_pAP->Get("N");
pDict->Add(m_sAP_N_Yes, m_pAP->GetYesN());
pDict = (CDictObject*)m_pAP->Get("D");
pDict->Add(m_sAP_N_Yes, m_pAP->GetYesD());
}
}
else if ((pAP = Get("AP")) && pAP->GetType() == object_type_DICT && (pAPN = ((CDictObject*)pAP)->Get("N")) && pAPN->GetType() == object_type_DICT && ((CDictObject*)pAPN)->Get(sV))
Add("AS", sV.c_str());
else if (nI >= 0 && m_pAP)
{
CDictObject* pDict = (CDictObject*)m_pAP->Get("N");
pDict->Add(std::to_string(nI), m_pAP->GetYesN());
pDict->Remove("Yes");
pDict = (CDictObject*)m_pAP->Get("D");
pDict->Add(std::to_string(nI), m_pAP->GetYesD());
pDict->Remove("Yes");
}
}
void CCheckBoxWidget::SetFlag(const int& nFlag)
{
if (nFlag < 0)
return;
int nFlags = nFlag;
if (nFlags & (1 << 15))
m_nSubtype = WidgetRadiobutton;
CWidgetAnnotation::SetFlag(nFlags);
}
std::string CCheckBoxWidget::GetTC(bool bCAPS)
{
std::string sDA = GetColor(m_arrTC, bCAPS);
if (sDA.empty())
sDA = bCAPS ? "0 G" : "0 g";
sDA += "\012";
return sDA;
}
//----------------------------------------------------------------------------------------
// CTextWidget
//----------------------------------------------------------------------------------------
CTextWidget::CTextWidget(CXref* pXref) : CWidgetAnnotation(pXref, AnnotWidget)
{
m_bAPV = false;
}
void CTextWidget::SetMaxLen(const int& nMaxLen)
{
if (nMaxLen > 0)
{
CDictObject* pOwner = GetObjOwnValue("MaxLen");
if (!pOwner)
pOwner = this;
pOwner->Add("MaxLen", nMaxLen);
}
}
void CTextWidget::SetV(const std::wstring& wsV)
{
m_sV = U_TO_UTF8(wsV);
CDictObject* pOwner = GetObjOwnValue("V");
if (!pOwner)
pOwner = this;
pOwner->Add("V", new CStringObject(m_sV.c_str(), true));
}
void CTextWidget::SetRV(const std::wstring& wsRV)
{
std::string sValue = U_TO_UTF8(wsRV);
CDictObject* pOwner = GetObjOwnValue("RV");
if (!pOwner)
pOwner = this;
pOwner->Add("RV", new CStringObject(sValue.c_str(), true));
}
bool CTextWidget::IsCombFlag()
{
int nFlags = 0;
CNumberObject* pFf = (CNumberObject*)GetObjValue("Ff");
if (pFf)
nFlags = pFf->Get();
return (nFlags & (1 << 24));
}
bool CTextWidget::IsMultiLine()
{
int nFlags = 0;
CNumberObject* pFf = (CNumberObject*)GetObjValue("Ff");
if (pFf)
nFlags = pFf->Get();
return (nFlags & (1 << 12));
}
unsigned int CTextWidget::GetMaxLen()
{
CNumberObject* oMaxLen = (CNumberObject*)GetObjValue("MaxLen");
return oMaxLen ? oMaxLen->Get() : 0;
}
//----------------------------------------------------------------------------------------
// CChoiceWidget
//----------------------------------------------------------------------------------------
CChoiceWidget::CChoiceWidget(CXref* pXref) : CWidgetAnnotation(pXref, AnnotWidget)
{
m_dHeight = 0;
m_nTI = -1;
m_bAPV = false;
}
void CChoiceWidget::SetFlag(const int& nFlag)
{
if (nFlag < 0)
return;
int nFlags = nFlag;
if (m_nSubtype == WidgetCombobox)
nFlags |= (1 << 17);
CDictObject* pOwner = GetObjOwnValue("Ff");
if (!pOwner)
pOwner = this;
else
{
int nFlags2 = ((CNumberObject*)(pOwner->Get("Ff")))->Get();
if (nFlags2 & (1 << 19))
nFlags |= (1 << 19);
}
pOwner->Add("Ff", nFlags);
}
void CChoiceWidget::SetTI(const int& nTI)
{
m_nTI = nTI;
CDictObject* pOwner = GetObjOwnValue("TI");
if (!pOwner)
pOwner = this;
pOwner->Add("TI", nTI);
}
void CChoiceWidget::SetV(const std::wstring& wsV)
{
std::string sValue = U_TO_UTF8(wsV);
CDictObject* pOwner = GetObjOwnValue("V");
if (!pOwner)
pOwner = this;
pOwner->Add("V", new CStringObject(sValue.c_str(), true));
}
void CChoiceWidget::SetI(const std::vector<int>& arrI)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
CDictObject* pOwner = GetObjOwnValue("I");
if (!pOwner)
pOwner = this;
pOwner->Add("I", pArray);
for (int i = 0; i < arrI.size(); ++i)
pArray->Add(arrI[i]);
}
void CChoiceWidget::SetV(const std::vector<std::wstring>& arrV)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
CDictObject* pOwner = GetObjOwnValue("V");
if (!pOwner)
pOwner = this;
pOwner->Add("V", pArray);
for (int i = 0; i < arrV.size(); ++i)
pArray->Add(new PdfWriter::CStringObject(U_TO_UTF8(arrV[i]).c_str(), true));
}
void CChoiceWidget::SetOpt(const std::vector< std::pair<std::wstring, std::wstring> >& arrOpt)
{
m_arrOpt = arrOpt;
if (m_arrOpt.empty())
return;
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
CDictObject* pOwner = GetObjOwnValue("Opt");
if (!pOwner)
pOwner = this;
pOwner->Add("Opt", pArray);
for (const std::pair<std::wstring, std::wstring>& PV : arrOpt)
{
if (PV.first.empty())
{
std::string sValue = U_TO_UTF8(PV.second);
pArray->Add(new CStringObject(sValue.c_str(), true));
}
else
{
CArrayObject* pArray2 = new CArrayObject();
pArray->Add(pArray2);
std::string sValue = U_TO_UTF8(PV.first);
pArray2->Add(new CStringObject(sValue.c_str(), true));
sValue = U_TO_UTF8(PV.second);
pArray2->Add(new CStringObject(sValue.c_str(), true));
}
}
}
std::wstring CChoiceWidget::GetValue(const std::wstring& wsExportV)
{
for (int i = 0; i < m_arrOpt.size(); ++i)
{
if (( m_arrOpt[i].first.empty() && m_arrOpt[i].second == wsExportV) ||
(!m_arrOpt[i].first.empty() && m_arrOpt[i].first == wsExportV))
return m_arrOpt[i].second;
}
return wsExportV;
}
std::wstring CChoiceWidget::SetListBoxIndex(const std::vector<std::wstring>& arrV)
{
std::wstring sRes;
int i = 0;
if (m_nTI < 0)
{
// Ищем верхний элемент отрисовки
for (; i < m_arrOpt.size(); ++i)
{
if (( m_arrOpt[i].first.empty() && m_arrOpt[i].second == arrV.front()) ||
(!m_arrOpt[i].first.empty() && m_arrOpt[i].first == arrV.front()))
{
m_nTI = i;
break;
}
}
}
else
i = m_nTI;
if (m_nTI < 0)
return L"";
for (; i < m_arrOpt.size(); ++i)
sRes += (m_arrOpt[i].second + L"\n");
i = m_nTI;
for (const std::wstring& sV : arrV)
{
for (int j = i; j < m_arrOpt.size(); ++j)
{
if (( m_arrOpt[j].first.empty() && m_arrOpt[j].second == sV) ||
(!m_arrOpt[j].first.empty() && m_arrOpt[j].first == sV))
{
m_arrIndex.push_back(j - m_nTI);
i = j + 1;
break;
}
}
}
if (!sRes.empty())
{
sRes.pop_back();
return sRes;
}
return L"";
}
//----------------------------------------------------------------------------------------
// CSignatureWidget
//----------------------------------------------------------------------------------------
CSignatureWidget::CSignatureWidget(CXref* pXref) : CWidgetAnnotation(pXref, AnnotWidget)
{
}
//----------------------------------------------------------------------------------------
// CAction
//----------------------------------------------------------------------------------------
CAction::CAction(CXref* pXref)
{
pXref->Add(this);
Add("Type", "Action");
}
void CAction::SetType(const std::wstring& wsType)
{
m_sType = U_TO_UTF8(wsType);
}
void CAction::SetNext(CAction* pNext)
{
Add("Next", pNext);
}
//----------------------------------------------------------------------------------------
CActionResetForm::CActionResetForm(CXref* pXref) : CAction(pXref)
{
Add("S", "ResetForm");
Add("Flags", 1);
}
void CActionResetForm::SetFlags(int nFlag)
{
Add("Flags", nFlag);
}
void CActionResetForm::SetFields(const std::vector<std::wstring>& arrFileds)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("Fields", pArray);
for (const std::wstring& A : arrFileds)
{
std::string sValue = U_TO_UTF8(A);
pArray->Add(new CStringObject(sValue.c_str(), true));
}
}
//----------------------------------------------------------------------------------------
CActionJavaScript::CActionJavaScript(CXref* pXref) : CAction(pXref)
{
Add("S", "JavaScript");
}
void CActionJavaScript::SetJS(const std::wstring& wsJS)
{
std::string sValue = U_TO_UTF8(wsJS);
Add("JS", new CStringObject(sValue.c_str(), true));
}
//----------------------------------------------------------------------------------------
CActionGoTo::CActionGoTo(CXref* pXref) : CAction(pXref)
{
Add("S", "GoTo");
}
void CActionGoTo::SetDestination(CArrayObject* pDest)
{
Add("D", pDest);
}
//----------------------------------------------------------------------------------------
CActionURI::CActionURI(CXref* pXref) : CAction(pXref)
{
Add("S", "URI");
}
void CActionURI::SetURI(const std::wstring& wsURI)
{
std::string sValue = U_TO_UTF8(wsURI);
Add("URI", new CStringObject(sValue.c_str(), true));
}
//----------------------------------------------------------------------------------------
CActionHide::CActionHide(CXref* pXref) : CAction(pXref)
{
Add("S", "Hide");
}
void CActionHide::SetH(BYTE nH)
{
Add("H", !!nH);
}
void CActionHide::SetT(const std::vector<std::wstring>& arrT)
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("T", pArray);
for (const std::wstring& A : arrT)
{
std::string sValue = U_TO_UTF8(A);
pArray->Add(new CStringObject(sValue.c_str(), true));
}
}
//----------------------------------------------------------------------------------------
CActionNamed::CActionNamed(CXref* pXref) : CAction(pXref)
{
Add("S", "Named");
}
void CActionNamed::SetN(const std::wstring& wsN)
{
std::string sValue = U_TO_UTF8(wsN);
Add("N", sValue.c_str());
}
}