Files
core/PdfFile/SrcWriter/Field.cpp
2024-02-12 17:42:24 +03:00

2638 lines
74 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 "Field.h"
#include "Pages.h"
#include "Streams.h"
#include "Document.h"
#include "ResourcesDictionary.h"
#include "Types.h"
#include "Image.h"
#include "Font.h"
#include "Info.h"
#include "EncryptDictionary.h"
#include "Annotation.h"
#include <algorithm>
#include <math.h>
#include "../../DesktopEditor/common/SystemUtils.h"
#include "../../DesktopEditor/common/File.h"
#ifndef BS_DEF_WIDTH
#define BS_DEF_WIDTH 1
#endif
namespace PdfWriter
{
//----------------------------------------------------------------------------------------
// CFieldBase
//----------------------------------------------------------------------------------------
CFieldBase::CFieldBase(CXref* pXref, CDocument* pDocument)
{
pXref->Add(this);
Add("Ff", (unsigned int)0);
m_pXref = pXref;
m_pDocument = pDocument;
m_nBorderType = 0;
m_dBorderSize = 0;
m_bAutoFit = false;
m_bShd = false;
m_pMK = NULL;
m_pParent = NULL;
m_pKids = NULL;
m_pAppearance = NULL;
m_pFocus = NULL;
m_pBlur = NULL;
}
void CFieldBase::SetReadOnlyFlag(bool isReadOnly)
{
SetFlag(isReadOnly, 1 << 0);
}
void CFieldBase::SetRequiredFlag(bool isRequired)
{
SetFlag(isRequired, 1 << 1);
}
void CFieldBase::SetNoExportFlag(bool isNoExport)
{
SetFlag(isNoExport, 1 << 2);
}
void CFieldBase::SetFlag(bool isFlag, int nBit)
{
int nFlags = ((CNumberObject*)this->Get("Ff"))->Get();
if ((nFlags & nBit) && !isFlag)
{
nFlags &= 0xffffffff ^ nBit;
}
else if (!(nFlags & nBit) && isFlag)
{
nFlags |= nBit;
}
Add("Ff", nFlags);
}
CDictObject* CFieldBase::GetAA()
{
CDictObject* pAA = dynamic_cast<CDictObject*>(this->Get("AA"));
if (pAA)
return pAA;
pAA = new CDictObject();
if (!pAA)
return NULL;
Add("AA", pAA);
return pAA;
}
void CFieldBase::AddScriptToAA(const std::string& sKey, const std::string& sScript, CDictObject* pAA)
{
if (sScript.empty())
return;
if (!pAA)
pAA = GetAA();
if (!pAA)
return;
CDictObject* pKey = new CDictObject();
if (!pKey)
return;
m_pXref->Add(pKey);
pAA->Add(sKey.c_str(), pKey);
pKey->Add("S", "JavaScript");
pKey->Add("JS", new CStringObject(sScript.c_str(), true, true));
}
void CFieldBase::AddPageRect(CPage* pPage, const TRect& oRect)
{
if (!pPage)
return;
pPage->AddAnnotation(this);
Add("Type", "Annot");
Add("Subtype", "Widget");
Add("P", pPage);
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("Rect", pArray);
if (oRect.fTop < oRect.fBottom)
{
pArray->Add(oRect.fLeft);
pArray->Add(oRect.fTop);
pArray->Add(oRect.fRight);
pArray->Add(oRect.fBottom);
m_oRect.fLeft = oRect.fLeft;
m_oRect.fTop = oRect.fTop;
m_oRect.fRight = oRect.fRight;
m_oRect.fBottom = oRect.fBottom;
}
else
{
pArray->Add(oRect.fLeft);
pArray->Add(oRect.fBottom);
pArray->Add(oRect.fRight);
pArray->Add(oRect.fTop);
m_oRect.fLeft = oRect.fLeft;
m_oRect.fTop = oRect.fBottom;
m_oRect.fRight = oRect.fRight;
m_oRect.fBottom = oRect.fTop;
}
Add("F", 4);
}
void CFieldBase::SetFieldName(const std::string& sName, bool isSkipCheck)
{
if (isSkipCheck || !m_pDocument->CheckFieldName(this, sName))
Add("T", new CStringObject(sName.c_str()));
}
void CFieldBase::SetFieldName(const std::wstring& wsName, bool isSkipCheck)
{
std::string sName = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(wsName);
if (isSkipCheck || !m_pDocument->CheckFieldName(this, sName))
Add("T", new CStringObject(sName.c_str(), true));
}
void CFieldBase::ClearKidRecords()
{
Remove("T");
Remove("FT");
Remove("Ff");
Remove("V");
}
void CFieldBase::SetFieldHint(const std::wstring& wsHint)
{
if (wsHint != L"")
{
std::string sHint = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(wsHint);
Add("TU", new CStringObject(sHint.c_str(), true));
}
else
{
Remove("TU");
}
}
TRect& CFieldBase::GetRect()
{
return m_oRect;
}
CResourcesDict* CFieldBase::GetResourcesDict()
{
return m_pDocument->GetFieldsResources();
}
void CFieldBase::SetDefaultAppearance(CFontDict* pFont, const double& dFontSize, const TRgb& oColor)
{
CResourcesDict* pFieldsResources = m_pDocument->GetFieldsResources();
const char* sFontName = pFieldsResources->GetFontName(pFont);
if (!sFontName)
return;
std::string sDA;
sDA.append(std::to_string(oColor.r));
sDA.append(" ");
sDA.append(std::to_string(oColor.g));
sDA.append(" ");
sDA.append(std::to_string(oColor.b));
sDA.append(" rg /");
sDA.append(sFontName);
if (IsAutoFit())
{
sDA.append(" 0 Tf");
}
else
{
sDA.append(" ");
sDA.append(std::to_string(dFontSize));
sDA.append(" Tf");
}
Add("DA", new CStringObject(sDA.c_str(), false, true));
}
void CFieldBase::SetTextAppearance(const std::wstring& wsValue, unsigned short* pCodes, unsigned int unCount, CFontDict* pFont, const TRgb& oColor, const double& dAlpha, double dFontSize, double dX, double dY, CFontCidTrueType** ppFonts, double* pShifts)
{
CAnnotAppearance* pAppearance = new CAnnotAppearance(m_pXref, this);
Add("AP", pAppearance);
CAnnotAppearanceObject* pNormal = pAppearance->GetNormal();
CResourcesDict* pFieldsResources = m_pDocument->GetFieldsResources();
const char* sExtGrStateName = NULL;
if (fabs(dAlpha - 1.0) > 0.001)
{
CExtGrState* pExtGrState = m_pDocument->GetFillAlpha(dAlpha);
sExtGrStateName = pFieldsResources->GetExtGrStateName(pExtGrState);
}
pNormal->DrawSimpleText(wsValue, pCodes, unCount, pFont, dFontSize, dX, dY, oColor.r, oColor.g, oColor.b, sExtGrStateName, fabs(m_oRect.fRight - m_oRect.fLeft), fabs(m_oRect.fBottom - m_oRect.fTop), ppFonts, pShifts);
}
void CFieldBase::StartTextAppearance(CFontDict* pFont, const double& dFontSize, const TRgb& oColor, const double& dAlpha)
{
m_pAppearance = new CAnnotAppearance(m_pXref, this);
if (!m_pAppearance)
return;
Add("AP", m_pAppearance);
CAnnotAppearanceObject* pNormal = m_pAppearance->GetNormal();
CResourcesDict* pFieldsResources = GetResourcesDict();
const char* sExtGrStateName = NULL;
if (fabs(dAlpha - 1.0) > 0.001)
{
CExtGrState* pExtGrState = m_pDocument->GetFillAlpha(dAlpha);
sExtGrStateName = pFieldsResources->GetExtGrStateName(pExtGrState);
}
pNormal->StartDrawText(pFont, dFontSize, oColor.r, oColor.g, oColor.b, sExtGrStateName, fabs(m_oRect.fRight - m_oRect.fLeft), fabs(m_oRect.fBottom - m_oRect.fTop));
}
void CFieldBase::AddLineToTextAppearance(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 CFieldBase::EndTextAppearance()
{
if (!m_pAppearance)
return;
CAnnotAppearanceObject* pNormal = m_pAppearance->GetNormal();
pNormal->EndDrawText();
}
void CFieldBase::SetTextValue(const std::wstring &wsValue)
{
std::string sValue = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(wsValue);
Add("V", new CStringObject(sValue.c_str(), true));
}
void CFieldBase::SetFieldBorder(const EBorderSubtype& eSubtype, const TRgb& oColor, const double& dWidth, const unsigned short& nDashOn, const unsigned short& nDashOff, const unsigned short& nDashPhase)
{
if (dWidth < 0.01)
{
m_nBorderType = 0;
Remove("BS");
return;
}
CDictObject* pBorderStyleDict = new CDictObject();
if (!pBorderStyleDict)
return;
Add("BS", pBorderStyleDict);
// PDF ридеры воспринимают только целочисленные значения толщины линии
int nWidth = (int)(dWidth + 0.5);
if (nWidth < 1)
nWidth = 1;
pBorderStyleDict->Add("W", nWidth);
if (border_subtype_Dashed == eSubtype)
{
CArrayObject* pDash = new CArrayObject();
if (!pDash)
return;
pBorderStyleDict->Add("D", pDash);
pBorderStyleDict->Add("Type", "Border");
pDash->Add(nDashOn);
pDash->Add(nDashOff);
if (0 != nDashPhase)
pDash->Add(nDashOff);
}
switch (eSubtype)
{
case border_subtype_Solid: pBorderStyleDict->Add("S", "S"); break;
case border_subtype_Dashed: pBorderStyleDict->Add("S", "D"); break;
case border_subtype_Beveled: pBorderStyleDict->Add("S", "B"); break;
case border_subtype_Inset: pBorderStyleDict->Add("S", "I"); break;
case border_subtype_Underlined: pBorderStyleDict->Add("S", "U"); break;
}
if (!m_pMK)
{
m_pMK = new CDictObject();
Add("MK", m_pMK);
}
if (!m_pMK)
return;
CArrayObject* pColor = new CArrayObject();
pColor->Add(oColor.r);
pColor->Add(oColor.g);
pColor->Add(oColor.b);
m_pMK->Add("BC", pColor);
m_nBorderType = 1;
m_dBorderSize = nWidth;
m_oBorderColor = oColor;
}
bool CFieldBase::HaveBorder() const
{
return m_nBorderType == 1;
}
const double& CFieldBase::GetBorderSize() const
{
return m_dBorderSize;
}
const TRgb& CFieldBase::GetBorderColor() const
{
return m_oBorderColor;
}
const bool& CFieldBase::IsAutoFit() const
{
return m_bAutoFit;
}
void CFieldBase::SetAutoFit(const bool& isAutoFit)
{
m_bAutoFit = isAutoFit;
}
bool CFieldBase::HaveShd() const
{
return m_bShd;
}
void CFieldBase::SetShd(const TRgb& oRgb)
{
m_oShdColor = oRgb;
if (!m_pMK)
{
m_pMK = new CDictObject();
Add("MK", m_pMK);
}
if (!m_pMK)
return;
CArrayObject* pBG = new CArrayObject();
if (pBG)
{
pBG->Add(oRgb.r);
pBG->Add(oRgb.g);
pBG->Add(oRgb.b);
m_pMK->Add("BG", pBG);
}
m_bShd = true;
}
const TRgb& CFieldBase::GetShdColor() const
{
return m_oShdColor;
}
void CFieldBase::SetParent(CFieldBase* pParent)
{
m_pParent = pParent;
Add("Parent", pParent);
}
void CFieldBase::AddKid(CFieldBase* pChild)
{
if (!m_pKids)
{
m_pKids = new CArrayObject();
Add("Kids", m_pKids);
}
m_pKids->Add(pChild);
}
int CFieldBase::GetKidsCount() const
{
if (!m_pKids)
return 0;
return m_pKids->GetCount();
}
int CFieldBase::GetFieldFlag() const
{
return ((CNumberObject*)Get("Ff"))->Get();
}
const char* CFieldBase::GetFieldType() const
{
return ((CNameObject*)Get("FT"))->Get();
}
void CFieldBase::SetAlign(const EFieldAlignType& eType)
{
Add("Q", (int)eType);
}
void CFieldBase::SetPlaceHolderText(const std::wstring& wsText, const TRgb& oNormalColor, const TRgb& oPlaceHolderColor)
{
m_wsPlaceHolderText = wsText;
m_oNormalColor = oNormalColor;
m_oPlaceHolderColor = oPlaceHolderColor;
SetPlaceHolderText(std::vector<std::wstring>{wsText}, {oNormalColor}, {oPlaceHolderColor});
if (m_pParent)
m_pParent->UpdateKidsPlaceHolder();
}
void CFieldBase::SetPlaceHolderText(const std::vector<std::wstring>& vPlaceHolders, const std::vector<TRgb>& vNormalColors, const std::vector<TRgb>& vPlaceHolderColors)
{
if (!vPlaceHolders.size() || !vNormalColors.size() || !vPlaceHolderColors.size())
return;
std::string sFocus = "\nvar curColor = color.convert(event.target.textColor, \"RGB\");\nif ((";
for (unsigned int unIndex = 0, unCount = vPlaceHolders.size(); unIndex < unCount; ++unIndex)
{
if (unIndex)
sFocus += " || ";
std::string sText = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(vPlaceHolders[unIndex]);
sFocus += "event.target.value==\"" + sText + "\"";
}
sFocus += ") && (";
for (unsigned int unIndex = 0, unCount = vPlaceHolderColors.size(); unIndex < unCount; ++unIndex)
{
if (unIndex)
sFocus += " || ";
const TRgb& oColor = vPlaceHolderColors[unIndex];
sFocus += "(Math.abs(curColor[1] - " + std::to_string(oColor.r) +
") < 0.005 && Math.abs(curColor[2] - " + std::to_string(oColor.g) +
") < 0.005 && Math.abs(curColor[3] - " + std::to_string(oColor.b) +
") < 0.005)";
}
sFocus += "))\n{ event.target.value = \"\";\n event.target.textColor =[\"RGB\", " +
std::to_string(vNormalColors[vNormalColors.size() - 1].r) + ", " +
std::to_string(vNormalColors[vNormalColors.size() - 1].g) + ", " +
std::to_string(vNormalColors[vNormalColors.size() - 1].b) + "];\n}";
std::string sText = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(vPlaceHolders[vPlaceHolders.size() - 1]);
const TRgb& oColor = vPlaceHolderColors[vPlaceHolderColors.size() - 1];
std::string sBlur = "\nif (event.target.value == \"\")\n{\n event.target.textColor =[\"RGB\", " +
std::to_string(oColor.r) + ", " +
std::to_string(oColor.g) + ", " +
std::to_string(oColor.b) + "];\nevent.target.value = \"" + sText + "\";\n}";
if (!m_pFocus || !m_pBlur)
{
CDictObject* pAA = GetAA();
if (!pAA)
return;
CDictObject* pFocus = new CDictObject();
CDictObject* pBlur = new CDictObject();
if (!pFocus || !pBlur)
return;
m_pXref->Add(pFocus);
m_pXref->Add(pBlur);
m_pFocus = pFocus;
m_pBlur = pBlur;
pAA->Add("Bl", pBlur);
pAA->Add("Fo", pFocus);
}
m_pFocus->Add("S", "JavaScript");
m_pFocus->Add("JS", new CStringObject(sFocus.c_str(), true, true));
m_pBlur->Add("S", "JavaScript");
m_pBlur->Add("JS", new CStringObject(sBlur.c_str(), true, true));
}
void CFieldBase::UpdateKidsPlaceHolder()
{
std::vector<std::wstring> vText;
std::vector<TRgb> vPlaceHolderColor, vNormalColor;
if (m_pKids)
{
for (unsigned int unKidIndex = 0, unKidsCount = GetKidsCount(); unKidIndex < unKidsCount; ++unKidIndex)
{
CFieldBase* pKid = (CFieldBase*)m_pKids->Get(unKidIndex);
const std::wstring& wsText = pKid->GetPlaceHolderText();
if (wsText.empty())
continue;
const TRgb& oPColor = pKid->GetPlaceHolderColor();
const TRgb& oNColor = pKid->GetNormalColor();
bool isAdd = true;
for (unsigned int unIndex = 0, unCount = vText.size(); unIndex < unCount; ++unIndex)
{
if (vText[unIndex] == wsText)
{
isAdd = false;
break;
}
}
if (isAdd)
vText.push_back(wsText);
isAdd = true;
for (unsigned int unIndex = 0, unCount = vPlaceHolderColor.size(); unIndex < unCount; ++unIndex)
{
if (vPlaceHolderColor[unIndex] == oPColor)
{
isAdd = false;
break;
}
}
if (isAdd)
vPlaceHolderColor.push_back(oPColor);
isAdd = true;
for (unsigned int unIndex = 0, unCount = vNormalColor.size(); unIndex < unCount; ++unIndex)
{
if (vNormalColor[unIndex] == oNColor)
{
isAdd = false;
break;
}
}
if (isAdd)
vNormalColor.push_back(oNColor);
}
for (unsigned int unKidIndex = 0, unKidsCount = GetKidsCount(); unKidIndex < unKidsCount; ++unKidIndex)
{
CFieldBase* pKid = (CFieldBase*)m_pKids->Get(unKidIndex);
pKid->SetPlaceHolderText(vText, vNormalColor, vPlaceHolderColor);
}
}
}
const std::wstring& CFieldBase::GetPlaceHolderText()
{
return m_wsPlaceHolderText;
}
const TRgb& CFieldBase::GetNormalColor()
{
return m_oNormalColor;
}
const TRgb& CFieldBase::GetPlaceHolderColor()
{
return m_oPlaceHolderColor;
}
void CFieldBase::SetFormat(const CFormFieldInfo::CTextFormFormat* pFormat)
{
if (!pFormat || pFormat->IsEmpty())
return;
std::string scriptK, scriptF, scriptV;
const TRgb& oNormalColor = GetNormalColor();
const std::string prefix = "var curColor = color.convert(event.target.textColor, \"RGB\");\nif (Math.abs(curColor[1] - " + std::to_string(oNormalColor.r) +
") < 0.005 && Math.abs(curColor[2] - " + std::to_string(oNormalColor.g) +
") < 0.005 && Math.abs(curColor[3] - " + std::to_string(oNormalColor.b) +
") < 0.005)\n{";
const std::string postfix = "}";
if (pFormat->GetSymbolsCount())
{
scriptK += "\nvar s=String.fromCharCode(";
scriptV += "\nvar s=String.fromCharCode(";
for (unsigned int unIndex = 0, unCount = pFormat->GetSymbolsCount(); unIndex < unCount; ++unIndex)
{
if (unIndex)
{
scriptK += ", ";
scriptV += ", ";
}
scriptK += std::to_string(pFormat->GetSymbol(unIndex));
scriptV += std::to_string(pFormat->GetSymbol(unIndex));
}
scriptK += ");";
scriptV += ");";
scriptK += "\nfor (var i = 0, l = event.change.length; i < l; ++i){\nvar c = event.change.charAt(i);\nif(-1 == s.indexOf(c)){\nevent.rc = false;\nbreak;\n}\n}";
scriptV += "\nfor (var i = 0, l = event.value.length; i < l; ++i){\nvar c = event.value.charAt(i);\nif(-1 == s.indexOf(c)){\nevent.rc = false;\nbreak;\n}\n}";
}
if (pFormat->IsDigit())
{
scriptK += "\nif(false !== event.rc)\n{for(var i = 0, l = event.change.length; i < l; ++i){var c = event.change.charCodeAt(i);if(c < 48 || c > 57){event.rc = false;break;}}}";
scriptV += "\nfor(var i = 0, l = event.value.length; i < l; ++i){var c = event.value.charCodeAt(i);if(c < 48 || c > 57){event.rc = false;break;}}";
}
else if (pFormat->IsLetter())
{
scriptK += "\nvar r=/^[^\\d.!?\\/\\\\+\\-\\x20'\":;\\(\\)\\[\\]\\{\\}=_@#$%^&*]+$/;\nif(false !== event.rc)\n{for(var i = 0, l = event.change.length; i < l; ++i){var c = event.change.charCodeAt(i);if(!r.test(String.fromCharCode(c))){event.rc = false;break;}}}";
scriptV += "\nvar r=/^[^\\d.!?\\/\\\\+\\-\\x20'\":;\\(\\)\\[\\]\\{\\}=_@#$%^&*]+$/;\nfor(var i = 0, l = event.value.length; i < l; ++i){var c = event.value.charCodeAt(i);if(!r.test(String.fromCharCode(c))){event.rc = false;break;}}";
}
else if (pFormat->IsMask())
{
scriptK += "\nAFSpecial_KeystrokeEx(\"" + NSFile::CUtf8Converter::GetUtf8StringFromUnicode(pFormat->GetMask()) + "\");";
}
else if (pFormat->IsRegExp())
{
scriptV += "\nvar r=/" + NSFile::CUtf8Converter::GetUtf8StringFromUnicode(pFormat->GetRegExp()) + "/;";
scriptV += "\nif(event.value)event.rc=!!event.value.match(r);";
}
CDictObject* pAA = GetAA();
if (!scriptK.empty())
{
scriptK = prefix + scriptK + postfix;
AddScriptToAA("K", scriptK, pAA);
}
if (!scriptV.empty())
{
scriptV = prefix + scriptV + postfix;
AddScriptToAA("V", scriptV, pAA);
}
if (!scriptF.empty())
{
scriptV = prefix + scriptF + postfix;
AddScriptToAA("F", scriptF, pAA);
}
}
//----------------------------------------------------------------------------------------
// CTextField
//----------------------------------------------------------------------------------------
CTextField::CTextField(CXref* pXref, CDocument* pDocument) : CFieldBase(pXref, pDocument)
{
Add("FT", "Tx");
m_bAutoFit = false;
}
void CTextField::SetMultilineFlag(bool isMultiLine)
{
SetFlag(isMultiLine, 1 << 12);
}
void CTextField::SetPasswordFlag(bool isPassword)
{
SetFlag(isPassword, 1 << 13);
}
void CTextField::SetFileSelectFlag(bool isFileSelect)
{
SetFlag(isFileSelect, 1 << 20);
}
void CTextField::SetDoNotSpellCheckFlag(bool isDoNotSpellCheck)
{
SetFlag(isDoNotSpellCheck, 1 << 22);
}
void CTextField::SetDoNotScrollFlag(bool isDoNotScroll)
{
SetFlag(isDoNotScroll, 1 << 23);
}
void CTextField::SetCombFlag(bool isComb)
{
SetFlag(isComb, 1 << 24);
}
void CTextField::SetRichTextFlag(bool isRichText)
{
SetFlag(isRichText, 1 << 25);
}
void CTextField::SetMaxLen(int nMaxLen)
{
if (nMaxLen > 0)
{
if (m_pParent)
m_pParent->Add("MaxLen", nMaxLen);
else
Add("MaxLen", nMaxLen);
}
}
int CTextField::GetMaxLen() const
{
CNumberObject* oMaxLen = (CNumberObject*)Get("MaxLen");
if (oMaxLen)
return oMaxLen->Get();
return 0;
}
bool CTextField::IsCombFlag() const
{
int nFlags = ((CNumberObject*)this->Get("Ff"))->Get();
return (nFlags & (1 << 24));
}
//----------------------------------------------------------------------------------------
// CChoiceField
//----------------------------------------------------------------------------------------
CChoiceField::CChoiceField(CXref* pXref, CDocument* pDocument) : CFieldBase(pXref, pDocument)
{
m_pOpt = NULL;
Add("FT", "Ch");
}
void CChoiceField::SetComboFlag(const bool& isCombo)
{
SetFlag(isCombo, 1 << 17);
}
void CChoiceField::SetEditFlag(const bool& isEdit)
{
SetFlag(isEdit, 1 << 18);
}
void CChoiceField::SetSortFlag(const bool& isSort)
{
SetFlag(isSort, 1 << 19);
}
void CChoiceField::SetMultiSelectFlag(const bool& isMultiSelect)
{
SetFlag(isMultiSelect, 1 << 21);
}
void CChoiceField::SetDoNotSpellCheck(const bool& isDoNotSpellCheck)
{
SetFlag(isDoNotSpellCheck, 1 << 22);
}
void CChoiceField::AddOption(const std::wstring& wsOption, const bool& bPushBack)
{
if (!m_pOpt)
{
m_pOpt = new CArrayObject();
Add("Opt", m_pOpt);
}
if (!m_pOpt)
return;
std::string sOption = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(wsOption);
m_pOpt->Add(new CStringObject(sOption.c_str(), true), bPushBack);
}
void CChoiceField::SetSelectedIndex(const unsigned int& unSelectedIndex)
{
if (m_pParent)
{
CChoiceField* pParent = dynamic_cast<CChoiceField*>(m_pParent);
if (pParent)
{
pParent->SetSelectedIndex(unSelectedIndex);
return;
}
}
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
pArray->Add(unSelectedIndex);
Add("I", pArray);
if (m_pKids)
{
for (unsigned int unIndex = 0, unCount = m_pKids->GetCount(); unIndex < unCount; ++unIndex)
{
CFieldBase* pKid = dynamic_cast<CFieldBase*>(m_pKids->Get(unIndex));
if (pKid)
pKid->Remove("I");
}
}
}
void CChoiceField::UpdateSelectedIndexToParent()
{
if (m_pParent)
{
CObjectBase* pSelectedArray = Get("I");
if (pSelectedArray)
m_pParent->Add("I", pSelectedArray->Copy());
Remove("I");
CObjectBase* pValue = Get("V");
if (pValue)
m_pParent->Add("V", pValue->Copy());
Remove("V");
CObjectBase* pOpt = Get("Opt");
if (pOpt)
m_pParent->Add("Opt", pOpt->Copy());
Remove("Opt");
}
}
void CChoiceField::SetPlaceHolderText(const std::wstring& wsText, const TRgb& oNormalColor, const TRgb& oPlaceHolderColor)
{
CDictObject* pAA = GetAA();
if (!pAA)
return;
CDictObject* pFocus = new CDictObject();
CDictObject* pBlur = new CDictObject();
if (!pFocus || !pBlur)
return;
bool bCanEdit = GetFieldFlag() & (1 << 18);
std::string sText = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(wsText);
std::string sFocus, sBlur;
if (!bCanEdit)
{
CDictObject* pChange = new CDictObject();
if (!pChange)
{
delete pFocus;
delete pBlur;
return;
}
// Если текст плейсхолдера не добавить как опцию, тогда AdobeAcrobat не дает выставлять такое текстовое значение
AddOption(wsText, false);
sFocus = "event.target.textColor = [\"RGB\", " +
std::to_string(oNormalColor.r) + ", " +
std::to_string(oNormalColor.g) + ", " +
std::to_string(oNormalColor.b) + "];";
sBlur = "\nif (event.target.value == \"" + sText + "\")\n event.target.textColor = [\"RGB\", " +
std::to_string(oPlaceHolderColor.r) + ", " +
std::to_string(oPlaceHolderColor.g) + ", " +
std::to_string(oPlaceHolderColor.b) + "];\nelse\n event.target.textColor = [\"RGB\", " +
std::to_string(oNormalColor.r) + ", " +
std::to_string(oNormalColor.g) + ", " +
std::to_string(oNormalColor.b) + "];";
std::string sChange = "\n if (event.value == \"" + sText + "\")\n event.target.textColor =[\"RGB\", " +
std::to_string(oPlaceHolderColor.r) + ", " +
std::to_string(oPlaceHolderColor.g) + ", " +
std::to_string(oPlaceHolderColor.b) + "];\n else\n event.target.textColor = [\"RGB\", " +
std::to_string(oNormalColor.r) + ", " +
std::to_string(oNormalColor.g) + ", " +
std::to_string(oNormalColor.b) + "];\n}";
m_pXref->Add(pChange);
pChange->Add("S", "JavaScript");
pChange->Add("JS", new CStringObject(sChange.c_str(), true, true));
pAA->Add("K", pChange);
}
else
{
sFocus = "var curColor = color.convert(event.target.textColor, \"RGB\");\nevent.target.textColor = [\"RGB\", " +
std::to_string(oNormalColor.r) + ", " +
std::to_string(oNormalColor.g) + ", " +
std::to_string(oNormalColor.b) + "];\nif (event.target.value == \"" + \
sText + "\" && Math.abs(curColor[1] - " + std::to_string(oPlaceHolderColor.r) +
") < 0.005 && Math.abs(curColor[2] - " + std::to_string(oPlaceHolderColor.g) +
") < 0.005 && Math.abs(curColor[3] - " + std::to_string(oPlaceHolderColor.b) +
") < 0.005)\n event.target.value = \"\";";
sBlur = "\nif (event.target.value == \"\")\n{\n event.target.textColor = [\"RGB\", " +
std::to_string(oPlaceHolderColor.r) + ", " +
std::to_string(oPlaceHolderColor.g) + ", " +
std::to_string(oPlaceHolderColor.b) + "];\nevent.target.value = \"" + sText + "\";\n}";
}
m_pXref->Add(pFocus);
pFocus->Add("S", "JavaScript");
pFocus->Add("JS", new CStringObject(sFocus.c_str(), true, true));
pAA->Add("Fo", pFocus);
m_pXref->Add(pBlur);
pBlur->Add("S", "JavaScript");
pBlur->Add("JS", new CStringObject(sBlur.c_str(), true, true));
pAA->Add("Bl", pBlur);
}
//----------------------------------------------------------------------------------------
// CCheckBoxField
//----------------------------------------------------------------------------------------
CCheckBoxField::CCheckBoxField(CXref* pXref, CDocument* pDocument, CRadioGroupField* pGroup, const char* sYesName) : CFieldBase(pXref, pDocument)
{
Add("FT", "Btn");
m_pGroup = pGroup;
if (pGroup)
Add("Parent", pGroup);
m_sYesName = sYesName ? sYesName : "Yes";
Add("AS", "Off");
}
void CCheckBoxField::SetAppearance(const std::wstring& wsYesValue, unsigned short* pYesCodes, unsigned int unYesCount, CFontDict* pYesFont,
const std::wstring& wsOffValue, unsigned short* pOffCodes, unsigned int unOffCount, CFontDict* pOffFont,
const TRgb& oColor, const double& dAlpha, double dFontSize, double dX, double dY)
{
CCheckBoxAnnotAppearance* pAppearance = new CCheckBoxAnnotAppearance(m_pXref, this, m_sYesName.c_str());
Add("AP", pAppearance);
if (!m_pMK)
{
m_pMK = new CDictObject();
m_pXref->Add(m_pMK);
Add("MK", m_pMK);
}
if (!m_nBorderType)
{
CArrayObject* pArray = new CArrayObject();
pArray->Add(0);
m_pMK->Add("BC", pArray);
}
if (!m_bShd)
{
CArrayObject* pArray = new CArrayObject();
pArray->Add(1);
m_pMK->Add("BG", pArray);
}
CResourcesDict* pFieldsResources = m_pDocument->GetFieldsResources();
const char* sFontName = pFieldsResources->GetFontName(pYesFont);
if (!sFontName)
return;
std::string sDA;
sDA.append(std::to_string(oColor.r));
sDA.append(" ");
sDA.append(std::to_string(oColor.g));
sDA.append(" ");
sDA.append(std::to_string(oColor.b));
sDA.append(" rg /");
sDA.append(sFontName);
sDA.append(" ");
sDA.append(std::to_string(0));
sDA.append(" Tf");
Add("DA", new CStringObject(sDA.c_str()));
const char* sExtGrStateName = NULL;
if (fabs(dAlpha - 1.0) > 0.001)
{
CExtGrState* pExtGrState = m_pDocument->GetFillAlpha(dAlpha);
sExtGrStateName = pFieldsResources->GetExtGrStateName(pExtGrState);
}
pAppearance->GetYesN()->DrawSimpleText(wsYesValue, pYesCodes, unYesCount, pYesFont, dFontSize, dX, dY, oColor.r, oColor.g, oColor.b, sExtGrStateName, fabs(m_oRect.fRight - m_oRect.fLeft), fabs(m_oRect.fBottom - m_oRect.fTop));
pAppearance->GetOffN()->DrawSimpleText(wsOffValue, pOffCodes, unOffCount, pOffFont, dFontSize, dX, dY, oColor.r, oColor.g, oColor.b, sExtGrStateName, fabs(m_oRect.fRight - m_oRect.fLeft), fabs(m_oRect.fBottom - m_oRect.fTop));
pAppearance->GetYesD()->DrawSimpleText(wsYesValue, pYesCodes, unYesCount, pYesFont, dFontSize, dX, dY, oColor.r, oColor.g, oColor.b, sExtGrStateName, fabs(m_oRect.fRight - m_oRect.fLeft), fabs(m_oRect.fBottom - m_oRect.fTop));
pAppearance->GetOffD()->DrawSimpleText(wsOffValue, pOffCodes, unOffCount, pOffFont, dFontSize, dX, dY, oColor.r, oColor.g, oColor.b, sExtGrStateName, fabs(m_oRect.fRight - m_oRect.fLeft), fabs(m_oRect.fBottom - m_oRect.fTop));
}
void CCheckBoxField::SetAppearance(const int& nType, const TRgb& oColor, const double& dAlpha, double dFontSize, double dX, double dY)
{
if (!m_pMK)
{
m_pMK = new CDictObject();
m_pXref->Add(m_pMK);
Add("MK", m_pMK);
}
CArrayObject* pArray = new CArrayObject();
pArray->Add(3);
m_pMK->Add("BC", pArray);
pArray = new CArrayObject();
pArray->Add(1);
pArray->Add(1);
pArray->Add(1);
m_pMK->Add("BG", pArray);
CCheckBoxAnnotAppearance* pAppearance = new CCheckBoxAnnotAppearance(m_pXref, this, m_sYesName.c_str());
Add("AP", pAppearance);
CFontDict* pFont = (CFontDict*)m_pDocument->GetDefaultCheckboxFont();
CResourcesDict* pFieldsResources = m_pDocument->GetFieldsResources();
const char* sFontName = pFieldsResources->GetFontName(pFont);
if (!sFontName)
return;
std::string sDA;
sDA.append(std::to_string(oColor.r));
sDA.append(" ");
sDA.append(std::to_string(oColor.g));
sDA.append(" ");
sDA.append(std::to_string(oColor.b));
sDA.append(" rg /");
sDA.append(sFontName);
sDA.append(" ");
sDA.append(std::to_string(0));
sDA.append(" Tf");
Add("DA", new CStringObject(sDA.c_str()));
const char* sExtGrStateName = NULL;
if (fabs(dAlpha - 1.0) > 0.001)
{
CExtGrState* pExtGrState = m_pDocument->GetFillAlpha(dAlpha);
sExtGrStateName = pFieldsResources->GetExtGrStateName(pExtGrState);
}
double dW = fabs(m_oRect.fRight - m_oRect.fLeft);
double dH = fabs(m_oRect.fBottom - m_oRect.fTop);
dFontSize = dH * 31.014 / 33.8712;
dX = 5.4407 * dW / 37.119000;
dY = 6.4375 * dH / 33.8712;
SetFieldBorder(border_subtype_Solid, TRgb(0.0, 0.0, 0.0), 1, 0, 0, 0);
Remove("BS");
if (1 == nType)
{
m_pMK->Add("CA", new CStringObject("4"));
pAppearance->GetYesN()->DrawSimpleText(L"4", NULL, 0, pFont, dFontSize, dX, dY, oColor.r, oColor.g, oColor.b, sExtGrStateName, dW, dH);
pAppearance->GetOffN()->DrawSimpleText(L"", NULL, 0, pFont, dFontSize, dX, dY, oColor.r, oColor.g, oColor.b, sExtGrStateName, dW, dH);
}
else if (2 == nType)
{
m_pMK->Add("CA", new CStringObject("1"));
pAppearance->GetYesN()->DrawSimpleText(L"1", NULL, 0, pFont, dFontSize, dX, dY, oColor.r, oColor.g, oColor.b, sExtGrStateName, dW, dH);
pAppearance->GetOffN()->DrawSimpleText(L"", NULL, 0, pFont, dFontSize, dX, dY, oColor.r, oColor.g, oColor.b, sExtGrStateName, dW, dH);
}
}
void CCheckBoxField::SetValue(const bool& isYes)
{
const char* sValue = (isYes ? m_sYesName.c_str() : "Off");
Add("AS", sValue);
Add("V", sValue);
}
//----------------------------------------------------------------------------------------
// CRadioGroupField
//----------------------------------------------------------------------------------------
CRadioGroupField::CRadioGroupField(CXref* pXref, CDocument* pDocument) : CFieldBase(pXref, pDocument)
{
Add("FT", "Btn");
SetFlag(true, 1 << 14);
SetFlag(true, 1 << 15);
m_pKids = new CArrayObject();
if (m_pKids)
Add("Kids", m_pKids);
}
CCheckBoxField* CRadioGroupField::CreateKid(const wchar_t* wsChoiceName)
{
if (!m_pKids)
return NULL;
std::string sName = wsChoiceName ? NSFile::CUtf8Converter::GetUtf8StringFromUnicode(wsChoiceName) : "Choice" + std::to_string(m_pKids->GetCount() + 1);
CCheckBoxField* pKid = new CCheckBoxField(m_pXref, m_pDocument, this, sName.c_str());
m_pKids->Add(pKid);
return pKid;
}
void CRadioGroupField::SetFieldName(const std::wstring& wsFieldName, bool isSkipCheck)
{
m_wsFieldName = wsFieldName;
CFieldBase::SetFieldName(wsFieldName, true);
}
const std::wstring& CRadioGroupField::GetFieldName() const
{
return m_wsFieldName;
}
//----------------------------------------------------------------------------------------
// CPictureField
//----------------------------------------------------------------------------------------
CPictureField::CPictureField(CXref* pXref, CDocument* pDocument) : CFieldBase(pXref, pDocument)
{
m_pMK = NULL;
m_pIF = NULL;
Add("FT", "Btn");
SetFlag(true, 1 << 16);
Add("H", "I");
CDictObject* pAction = new CDictObject();
if (pAction)
{
pXref->Add(pAction);
Add("A", pAction);
pAction->Add("Type", "Action");
pAction->Add("S", "JavaScript");
pAction->Add("JS", new CStringObject("event.target.buttonImportIcon();"));
}
m_pMK = new CDictObject();
if (!m_pMK)
return;
pXref->Add(m_pMK);
Add("MK", m_pMK);
m_pMK->Add("R", 0);
m_pMK->Add("TP", 1);
m_pIF = new CDictObject();
if (!m_pIF)
return;
m_pMK->Add("IF", m_pIF);
SetScaleType(EScaleType::Always);
SetRespectBorders(false);
SetConstantProportions(true);
SetShift(0.5, 0.5);
m_pResources = NULL;
}
void CPictureField::SetFieldName(const std::string& sName, bool isSkipCheck)
{
std::string _sName = sName + "_af_image";
CFieldBase::SetFieldName(_sName, isSkipCheck);
}
void CPictureField::SetFieldName(const std::wstring& wsName, bool isSkipCheck)
{
std::string sName = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(wsName) + "_af_image";
CFieldBase::SetFieldName(sName, isSkipCheck);
}
void CPictureField::SetAppearance(CImageDict* pImage)
{
CAnnotAppearance* pAppearance = new CAnnotAppearance(m_pXref, this);
Add("AP", pAppearance);
CAnnotAppearanceObject* pNormal = pAppearance->GetNormal();
CResourcesDict* pFieldsResources = GetResourcesDict();
std::string sDA = "0.909 0.941 0.992 rg";
Add("DA", new CStringObject(sDA.c_str()));
if (pImage)
{
TRect oRect = GetRect();
double dH = fabs(oRect.fTop - oRect.fBottom);
double dW = fabs(oRect.fRight - oRect.fLeft);
double dOriginW = pImage->GetWidth() * 72 / 96.0;
double dOriginH = pImage->GetHeight() * 72 / 96.0;
bool bNeedScale = (EScaleType::Always == m_eScaleType
|| (EScaleType::Bigger == m_eScaleType && (dOriginH > dH || dOriginW > dW))
|| (EScaleType::Smaller == m_eScaleType && dOriginH < dH && dOriginW < dW));
double dDstW = dOriginW;
double dDstH = dOriginH;
double dDstX = 0;
double dDstY = 0;
if (m_bRespectBorders && HaveBorder())
{
double dBorderSize = GetBorderSize();
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;
CXObject* pForm = new CXObject();
CStream* pStream = new CMemoryStream();
pForm->SetStream(m_pXref, pStream);
#ifndef FILTER_FLATE_DECODE_DISABLED
if (m_pDocument->GetCompressionMode() & COMP_TEXT)
pForm->SetFilter(STREAM_FILTER_FLATE_DECODE);
#endif
CArrayObject* pBBox = new CArrayObject();
pForm->Add("BBox", pBBox);
pBBox->Add(0);
pBBox->Add(0);
pBBox->Add(dOriginW);
pBBox->Add(dOriginH);
pForm->Add("FormType", 1);
CArrayObject* pFormMatrix = new CArrayObject();
pForm->Add("Matrix", pFormMatrix);
pFormMatrix->Add(1);
pFormMatrix->Add(0);
pFormMatrix->Add(0);
pFormMatrix->Add(1);
pFormMatrix->Add(0);
pFormMatrix->Add(0);
pForm->Add("Name", "FRM");
CDictObject* pFormRes = new CDictObject();
CArrayObject* pFormResProcset = new CArrayObject();
pFormRes->Add("ProcSet", pFormResProcset);
pFormResProcset->Add(new CNameObject("PDF"));
pFormResProcset->Add(new CNameObject("ImageC"));
CDictObject* pFormResXObject = new CDictObject();
pFormRes->Add("XObject", pFormResXObject);
pFormResXObject->Add("Img", pImage);
pForm->Add("Resources", pFormRes);
pForm->Add("Subtype", "Form");
pForm->Add("Type", "XObject");
pStream->WriteStr("q\012");
pStream->WriteReal(dOriginW);
pStream->WriteStr(" 0 0 ");
pStream->WriteReal(dOriginH);
pStream->WriteStr(" 0 0 cm\012/Img Do\012Q");
pFieldsResources->AddXObjectWithName("FRM", pForm);
pNormal->DrawPicture("FRM", dDstX, dDstY, dDstW / dOriginW, dDstH / dOriginH, m_bRespectBorders);
}
else
{
pNormal->DrawPicture();
}
}
void CPictureField::SetScaleType(const EScaleType& eType)
{
if (!m_pIF)
return;
switch (eType)
{
case EScaleType::Always: m_pIF->Add("SW", "A"); break;
case EScaleType::Bigger: m_pIF->Add("SW", "B"); break;
case EScaleType::Smaller: m_pIF->Add("SW", "S"); break;
case EScaleType::Never: m_pIF->Add("SW", "N"); break;
}
m_eScaleType = eType;
}
void CPictureField::SetConstantProportions(const bool& bConstant)
{
if (!m_pIF)
return;
if (bConstant)
m_pIF->Add("S", "P");
else
m_pIF->Add("S", "A");
m_bConstantProportions = bConstant;
}
void CPictureField::SetRespectBorders(const bool& bRespectBorders)
{
if (!m_pIF)
return;
m_pIF->Add("FB", !bRespectBorders);
m_bRespectBorders = bRespectBorders;
}
void CPictureField::SetShift(const double& dX, const double& dY)
{
if (!m_pIF)
return;
CArrayObject* pA = new CArrayObject();
if (pA)
{
m_pIF->Add("A", pA);
pA->Add(dX);
pA->Add(dY);
}
m_dShiftX = dX;
m_dShiftY = dY;
}
CResourcesDict* CPictureField::GetResourcesDict()
{
if (!m_pResources)
m_pResources = new CResourcesDict(m_pXref, false, true);
return m_pResources;
}
//----------------------------------------------------------------------------------------
// CSignatureField
//----------------------------------------------------------------------------------------
CSignatureField::CSignatureField(CXref* pXref, CDocument* pDocument) : CFieldBase(pXref, pDocument)
{
// Словарь сигнатур
m_pSig = new CSignatureDict(pXref);
if (!m_pSig)
return;
Add("V", m_pSig);
Add("FT", "Sig");
m_pResources = NULL;
}
void CSignatureField::SetName(const std::wstring& wsValue)
{
if (!m_pSig || wsValue.empty())
return;
m_pSig->SetName(U_TO_UTF8(wsValue));
}
void CSignatureField::SetReason(const std::wstring &wsValue)
{
if (!m_pSig || wsValue.empty())
return;
m_pSig->SetReason(U_TO_UTF8(wsValue));
}
void CSignatureField::SetContact(const std::wstring &wsValue)
{
if (!m_pSig || wsValue.empty())
return;
m_pSig->SetContact(U_TO_UTF8(wsValue));
}
void CSignatureField::SetCert()
{
}
void CSignatureField::SetDate(bool bDate)
{
if (!m_pSig || !bDate)
return;
m_pSig->SetDate();
}
void CSignatureField::SetAppearance(CImageDict* pImage)
{
CAnnotAppearance* pAppearance = new CAnnotAppearance(m_pXref, this);
Add("AP", pAppearance);
CAnnotAppearanceObject* pNormal = pAppearance->GetNormal();
CResourcesDict* pFieldsResources = GetResourcesDict();
std::string sDA = "0.909 0.941 0.992 rg";
Add("DA", new CStringObject(sDA.c_str()));
if (pImage)
{
TRect oRect = GetRect();
double dH = fabs(oRect.fTop - oRect.fBottom);
double dW = fabs(oRect.fRight - oRect.fLeft);
double dOriginW = pImage->GetWidth() * 72 / 96.0;
double dOriginH = pImage->GetHeight() * 72 / 96.0;
double dDstW = dOriginW;
double dDstH = dOriginH;
double dDstX = 0;
double dDstY = 0;
if (HaveBorder())
{
double dBorderSize = GetBorderSize();
dDstX += 2 * dBorderSize;
dDstY += 2 * dBorderSize;
dH -= 4 * dBorderSize;
dW -= 4 * dBorderSize;
}
double dScaleKoef = fmin(dW / dOriginW, dH / dOriginH);
dDstW = dScaleKoef * dOriginW;
dDstH = dScaleKoef * dOriginH;
dDstX += (dW - dDstW) * 0.5;
dDstY += (dH - dDstH) * 0.5;
CXObject* pForm = new CXObject();
CStream* pStream = new CMemoryStream();
pForm->SetStream(m_pXref, pStream);
#ifndef FILTER_FLATE_DECODE_DISABLED
if (m_pDocument->GetCompressionMode() & COMP_TEXT)
pForm->SetFilter(STREAM_FILTER_FLATE_DECODE);
#endif
CArrayObject* pBBox = new CArrayObject();
pForm->Add("BBox", pBBox);
pBBox->Add(0);
pBBox->Add(0);
pBBox->Add(dOriginW);
pBBox->Add(dOriginH);
pForm->Add("FormType", 1);
CArrayObject* pFormMatrix = new CArrayObject();
pForm->Add("Matrix", pFormMatrix);
pFormMatrix->Add(1);
pFormMatrix->Add(0);
pFormMatrix->Add(0);
pFormMatrix->Add(1);
pFormMatrix->Add(0);
pFormMatrix->Add(0);
pForm->Add("Name", "FRM");
CDictObject* pFormRes = new CDictObject();
CArrayObject* pFormResProcset = new CArrayObject();
pFormRes->Add("ProcSet", pFormResProcset);
pFormResProcset->Add(new CNameObject("PDF"));
pFormResProcset->Add(new CNameObject("ImageC"));
CDictObject* pFormResXObject = new CDictObject();
pFormRes->Add("XObject", pFormResXObject);
pFormResXObject->Add("Img", pImage);
pForm->Add("Resources", pFormRes);
pForm->Add("Subtype", "Form");
pForm->Add("Type", "XObject");
pStream->WriteStr("q\012");
pStream->WriteReal(dOriginW);
pStream->WriteStr(" 0 0 ");
pStream->WriteReal(dOriginH);
pStream->WriteStr(" 0 0 cm\012/Img Do\012Q");
pFieldsResources->AddXObjectWithName("FRM", pForm);
pNormal->DrawPicture("FRM", dDstX, dDstY, dDstW / dOriginW, dDstH / dOriginH, true);
}
else
{
pNormal->DrawPicture();
}
}
CResourcesDict* CSignatureField::GetResourcesDict()
{
if (!m_pResources)
m_pResources = new CResourcesDict(m_pXref, false, true);
return m_pResources;
}
//----------------------------------------------------------------------------------------
// CAnnotAppearance
//----------------------------------------------------------------------------------------
CDateTimeField::CDateTimeField(CXref* pXref, CDocument* pDocument) : CFieldBase(pXref, pDocument)
{
Add("FT", "Tx");
SetFormat("d-mmm-yyyy");
}
void CDateTimeField::SetFormat(const std::wstring& wsFormat)
{
SetFormat(NSFile::CUtf8Converter::GetUtf8StringFromUnicode(wsFormat));
}
void CDateTimeField::SetFormat(const std::string& sFormat)
{
std::string script = "AFDate_FormatEx(\"" + sFormat + "\");";
AddScriptToAA("F", script);
script = "AFDate_KeystrokeEx(\"" + sFormat + "\");";
AddScriptToAA("K", script);
}
//----------------------------------------------------------------------------------------
// CAnnotAppearance
//----------------------------------------------------------------------------------------
CAnnotAppearance::CAnnotAppearance(CXref* pXref, CFieldBase* pField)
{
m_pXref = pXref;
m_pField = pField;
m_pAnnot = NULL;
m_pNormal = new CAnnotAppearanceObject(pXref, pField);
m_pRollover = NULL;
m_pDown = NULL;
Add("N", m_pNormal);
}
CAnnotAppearance::CAnnotAppearance(CXref* pXref, CAnnotation* pAnnot)
{
m_pXref = pXref;
m_pAnnot = pAnnot;
m_pField = NULL;
m_pNormal = NULL;
m_pRollover = NULL;
m_pDown = NULL;
}
CAnnotAppearanceObject* CAnnotAppearance::GetNormal()
{
if (!m_pNormal)
{
if (m_pField)
m_pNormal = new CAnnotAppearanceObject(m_pXref, m_pField);
else if (m_pAnnot)
m_pNormal = new CAnnotAppearanceObject(m_pXref, m_pAnnot);
Add("N", m_pNormal);
}
return m_pNormal;
}
CAnnotAppearanceObject* CAnnotAppearance::GetRollover()
{
if (!m_pRollover)
{
if (m_pField)
m_pRollover = new CAnnotAppearanceObject(m_pXref, m_pField);
else if (m_pAnnot)
m_pRollover = new CAnnotAppearanceObject(m_pXref, m_pAnnot);
Add("R", m_pRollover);
}
return m_pRollover;
}
CAnnotAppearanceObject* CAnnotAppearance::GetDown()
{
if (!m_pDown)
{
if (m_pField)
m_pDown = new CAnnotAppearanceObject(m_pXref, m_pField);
else if (m_pAnnot)
m_pDown = new CAnnotAppearanceObject(m_pXref, m_pAnnot);
Add("D", m_pDown);
}
return m_pDown;
}
//----------------------------------------------------------------------------------------
// CCheckBoxAnnotAppearance
//----------------------------------------------------------------------------------------
CCheckBoxAnnotAppearance::CCheckBoxAnnotAppearance(CXref* pXref, CFieldBase* pField, const char* sYesName)
{
m_pXref = pXref;
m_pField = pField;
m_pYesN = new CAnnotAppearanceObject(pXref, pField);
m_pOffN = new CAnnotAppearanceObject(pXref, pField);
m_pYesD = new CAnnotAppearanceObject(pXref, pField);
m_pOffD = new CAnnotAppearanceObject(pXref, pField);
CDictObject* pDictN = new CDictObject();
Add("N", pDictN);
pDictN->Add(sYesName ? sYesName : "Yes", m_pYesN);
pDictN->Add("Off", m_pOffN);
CDictObject* pDictD = new CDictObject();
Add("D", pDictD);
pDictD->Add(sYesName ? sYesName : "Yes", m_pYesD);
pDictD->Add("Off", m_pOffD);
}
CAnnotAppearanceObject* CCheckBoxAnnotAppearance::GetYesN()
{
return m_pYesN;
}
CAnnotAppearanceObject* CCheckBoxAnnotAppearance::GetOffN()
{
return m_pOffN;
}
CAnnotAppearanceObject* CCheckBoxAnnotAppearance::GetYesD()
{
return m_pYesD;
}
CAnnotAppearanceObject* CCheckBoxAnnotAppearance::GetOffD()
{
return m_pOffD;
}
//----------------------------------------------------------------------------------------
// CAnnotAppearanceObject
//----------------------------------------------------------------------------------------
void CAnnotAppearanceObject::Init(CXref* pXref, CResourcesDict* pResources)
{
m_pXref = pXref ? pXref : NULL;
m_pStream = new CMemoryStream();
m_pFont = NULL;
m_dFontSize = 10.0;
if (m_pXref)
SetStream(m_pXref, m_pStream);
Add("Type", "XObject");
Add("Subtype", "Form");
Add("Resources", pResources);
}
CAnnotAppearanceObject::CAnnotAppearanceObject(CXref* pXref, CFieldBase* pField)
{
Init(pXref, pField->GetResourcesDict());
m_pField = pField;
m_pAnnot = NULL;
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("BBox", pArray);
pArray->Add(0);
pArray->Add(0);
pArray->Add(fabs(pField->GetRect().fRight - pField->GetRect().fLeft));
pArray->Add(fabs(pField->GetRect().fBottom - pField->GetRect().fTop));
}
CAnnotAppearanceObject::CAnnotAppearanceObject(CXref* pXRef, CAnnotation* pAnnot)
{
Init(pXRef, pAnnot->GetDocument()->GetFieldsResources());
m_pAnnot = pAnnot;
m_pField = NULL;
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("BBox", pArray);
if (pAnnot->GetAnnotationType() == EAnnotType::AnnotWidget)
{
pArray->Add(0);
pArray->Add(0);
pArray->Add(fabs(pAnnot->GetRect().fRight - pAnnot->GetRect().fLeft));
pArray->Add(fabs(pAnnot->GetRect().fBottom - pAnnot->GetRect().fTop));
}
else
{
pArray->Add(pAnnot->GetRect().fLeft);
pArray->Add(pAnnot->GetRect().fBottom);
pArray->Add(pAnnot->GetRect().fRight);
pArray->Add(pAnnot->GetRect().fTop);
pArray = new CArrayObject();
if (!pArray)
return;
Add("Matrix", pArray);
pArray->Add(1);
pArray->Add(0);
pArray->Add(0);
pArray->Add(1);
pArray->Add(-pAnnot->GetRect().fLeft);
pArray->Add(-pAnnot->GetRect().fBottom);
}
}
void CAnnotAppearanceObject::DrawSimpleText(const std::wstring& wsText, unsigned short* pCodes, unsigned int unCount, CFontDict* pFont, double dFontSize, double dX, double dY, double dR, double dG, double dB, const char* sExtGStateName, double dWidth, double dHeight, CFontCidTrueType** ppFonts, double* pShifts)
{
if (!m_pStream || !pFont)
return;
StartDrawText(pFont, dFontSize, dR, dG, dB, sExtGStateName, dWidth, dHeight);
if (pCodes)
DrawTextLine(dX, dY, pCodes, unCount, ppFonts, pShifts);
else
DrawTextLine(dX, dY, wsText);
EndDrawText();
}
void CAnnotAppearanceObject::DrawPicture(const char* sImageName, const double& dX, const double& dY, const double& dImageW, const double& dImageH, const bool& bRespectBorder)
{
if (!m_pStream)
return;
CWidgetAnnotation* pAnnot = NULL;
if (m_pAnnot)
pAnnot = (CWidgetAnnotation*)m_pAnnot;
double dW = 0, dH = 0;
if (m_pField || pAnnot)
{
TRect oRect = m_pField ? m_pField->GetRect() : pAnnot->GetRect();
dW = fabs(oRect.fRight - oRect.fLeft);
dH = fabs(oRect.fBottom - oRect.fTop);
}
m_pStream->WriteStr("q\012");
if ((m_pField && m_pField->HaveShd()) || (pAnnot && pAnnot->HaveBG()))
{
if (m_pField)
{
TRgb oColor = m_pField->GetShdColor();
m_pStream->WriteReal(oColor.r);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(oColor.g);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(oColor.b);
m_pStream->WriteStr(" rg\012");
}
else
{
m_pStream->WriteStr(pAnnot->GetBGforAP().c_str());
m_pStream->WriteStr("\012");
}
m_pStream->WriteStr("1 0 0 1 0 0 cm\012");
m_pStream->WriteStr("0 0 ");
m_pStream->WriteReal(fmax(dW, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(fmax(dH, 0.0));
m_pStream->WriteStr(" re\012f\012");
}
else if (!sImageName)
{
m_pStream->WriteStr("0.909 0.941 0.992 rg\0121 0 0 1 0 0 cm\012");
m_pStream->WriteStr("0 0 ");
m_pStream->WriteReal(fmax(dW, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(fmax(dH, 0.0));
m_pStream->WriteStr(" re\012f\012");
}
if ((m_pField && m_pField->HaveBorder()) || (pAnnot && pAnnot->HaveBorder()))
{
double dBorderSize = m_pField ? m_pField->GetBorderSize() : pAnnot->GetBorderWidth();
BYTE nType = 0;
if (pAnnot)
{
nType = pAnnot->GetBorderType();
switch (nType)
{
case 1: // Beveled
case 3: // Inset
{
m_pStream->WriteStr(nType == 1 ? "1 g\012" : "0.501953 g\012");
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" m\012");
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dH - dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dW - dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dH - dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dW - 2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dH - 2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dH - 2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteStr("f\012");
if (nType == 1 && pAnnot->HaveBG())
{
m_pStream->WriteStr(pAnnot->GetBGforAP(-0.25).c_str());
m_pStream->WriteStr("\012");
}
else
m_pStream->WriteStr("0.75293 g\012");
m_pStream->WriteReal(dW - dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dH - dBorderSize);
m_pStream->WriteStr(" m\012");
m_pStream->WriteReal(dW - dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dW - 2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dW - 2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dH - 2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteStr("f\012");
break;
}
case 2: // Dashed
{
m_pStream->WriteStr(pAnnot->GetBorderDash().c_str());
break;
}
default: break;
}
}
if (m_pField)
{
TRgb oColor = m_pField->GetBorderColor();
m_pStream->WriteReal(oColor.r);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(oColor.g);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(oColor.b);
m_pStream->WriteStr(" RG\012");
}
else
{
m_pStream->WriteStr(pAnnot->GetBCforAP().c_str());
m_pStream->WriteStr("\012");
}
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" w\0120 j\0120 J\012");
if (nType == 4) // Underline
{
m_pStream->WriteInt(0);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize / 2);
m_pStream->WriteStr(" m\012");
m_pStream->WriteReal(dW);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize / 2);
m_pStream->WriteStr(" l\012S\012");
}
else
{
m_pStream->WriteReal(dBorderSize / 2);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize / 2);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dW - dBorderSize, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dH - dBorderSize, 0.0));
m_pStream->WriteStr(" re\012S\012");
}
if (bRespectBorder && sImageName)
{
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(fmax(dW - 4 * dBorderSize, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(fmax(dH - 4 * dBorderSize, 0.0));
m_pStream->WriteStr(" re\012W\012n\012");
}
}
else if (!sImageName)
{
m_pStream->WriteStr("0.909 0.941 0.992 RG\012");
m_pStream->WriteStr("0.5 0.5 ");
m_pStream->WriteReal(fmax(dW - 1, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(fmax(dH - 1, 0.0));
m_pStream->WriteStr(" re\012s\012");
}
if (sImageName)
{
m_pStream->WriteReal(dImageW);
m_pStream->WriteStr(" 0 0 ");
m_pStream->WriteReal(dImageH);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dY);
m_pStream->WriteStr(" cm\012");
m_pStream->WriteEscapeName(sImageName);
m_pStream->WriteStr(" Do\012");
}
m_pStream->WriteStr("Q");
}
void CAnnotAppearanceObject::StartDrawText(CFontDict* pFont, const double& dFontSize, const double& dR, const double& dG, const double& dB, const char* sExtGStateName, const double& dWidth, const double& dHeight)
{
CResourcesDict* pResources = dynamic_cast<CResourcesDict*>(Get("Resources"));
if (!m_pStream || !pFont || !pResources)
return;
CWidgetAnnotation* pAnnot = NULL;
if (m_pAnnot)
pAnnot = (CWidgetAnnotation*)m_pAnnot;
m_pStream->WriteEscapeName("Tx");
m_pStream->WriteStr(" BMC\012");
if ((m_pField && m_pField->HaveShd()) || (pAnnot && pAnnot->HaveBG()))
{
m_pStream->WriteStr("q\012");
if (m_pField)
{
TRgb oColor = m_pField->GetShdColor();
m_pStream->WriteReal(oColor.r);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(oColor.g);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(oColor.b);
m_pStream->WriteStr(" rg\012");
}
else
{
m_pStream->WriteStr(pAnnot->GetBGforAP().c_str());
m_pStream->WriteStr("\012");
}
m_pStream->WriteStr("1 0 0 1 0 0 cm\012");
m_pStream->WriteStr("0 0 ");
m_pStream->WriteReal(fmax(dWidth, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(fmax(dHeight, 0.0));
m_pStream->WriteStr(" re\012f\012");
m_pStream->WriteStr("Q\012");
}
double dBorderSize = 0;
double dBorderSizeStyle = 0;
if (pAnnot && pAnnot->HaveBorder())
{
dBorderSize = pAnnot->GetBorderWidth();
dBorderSizeStyle = dBorderSize;
if (pAnnot->GetBorderType() == 1 || pAnnot->GetBorderType() == 3)
dBorderSizeStyle *= 2;
}
if ((m_pField && m_pField->HaveBorder()) || (pAnnot && pAnnot->HaveBorder() && pAnnot->HaveBC()))
{
m_pStream->WriteStr("q\012");
dBorderSize = m_pField ? m_pField->GetBorderSize() : pAnnot->GetBorderWidth();
dBorderSizeStyle = dBorderSize;
BYTE nType = 0;
if (pAnnot)
{
nType = pAnnot->GetBorderType();
switch (nType)
{
case 1: // Beveled
case 3: // Inset
{
dBorderSizeStyle *= 2;
m_pStream->WriteStr(nType == 1 ? "1 g\012" : "0.501953 g\012");
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" m\012");
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight - dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dWidth - dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight - dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dWidth - 2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight - 2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight - 2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteStr("f\012");
if (nType == 1 && pAnnot->HaveBG())
{
m_pStream->WriteStr(pAnnot->GetBGforAP(-0.25).c_str());
m_pStream->WriteStr("\012");
}
else
m_pStream->WriteStr("0.75293 g\012");
m_pStream->WriteReal(dWidth - dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight - dBorderSize);
m_pStream->WriteStr(" m\012");
m_pStream->WriteReal(dWidth - dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dWidth - 2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dWidth - 2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight - 2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteStr("f\012");
break;
}
case 2: // Dashed
{
m_pStream->WriteStr(pAnnot->GetBorderDash().c_str());
break;
}
default: break;
}
}
if (m_pField)
{
TRgb oColor = m_pField->GetBorderColor();
m_pStream->WriteReal(oColor.r);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(oColor.g);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(oColor.b);
m_pStream->WriteStr(" RG\012");
}
else
{
m_pStream->WriteStr(pAnnot->GetBCforAP().c_str());
m_pStream->WriteStr("\012");
}
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" w\0120 j\0120 J\012");
if (nType == 4) // Underline
{
m_pStream->WriteInt(0);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize / 2);
m_pStream->WriteStr(" m\012");
m_pStream->WriteReal(dWidth);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize / 2);
m_pStream->WriteStr(" l\012S\012");
}
else
{
m_pStream->WriteReal(dBorderSize / 2);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize / 2);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dWidth - dBorderSize, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dHeight - dBorderSize, 0.0));
m_pStream->WriteStr(" re\012S\012");
}
CTextField* pTextField = dynamic_cast<CTextField*>(m_pField);
CTextWidget* pAnnot = dynamic_cast<CTextWidget*>(m_pAnnot);
if ((pTextField && pTextField->IsCombFlag()) || (pAnnot && pAnnot->IsCombFlag() && (nType == 0 || nType == 2)))
{
int nMaxLen = pTextField ? pTextField->GetMaxLen() : pAnnot->GetMaxLen();
if (nMaxLen > 1)
{
double dStep = dWidth / nMaxLen;
double dX = dStep;
for (int nIndex = 0; nIndex < nMaxLen - 1; ++nIndex)
{
m_pStream->WriteReal(dX);
m_pStream->WriteChar(' ');
m_pStream->WriteInt(0);
m_pStream->WriteChar(' ');
m_pStream->WriteStr(" m\012");
m_pStream->WriteReal(dX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight);
m_pStream->WriteChar(' ');
m_pStream->WriteStr(" l\012S\012");
dX += dStep;
}
}
}
m_pStream->WriteStr("Q\012");
}
m_pStream->WriteStr("q\012");
if (pAnnot && pAnnot->GetWidgetType() == WidgetPushbutton && !((CPushButtonWidget*)pAnnot)->GetRespectBorder())
{
m_pStream->WriteStr("0 0 ");
m_pStream->WriteReal(std::max(dWidth, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dHeight, 0.0));
}
else
{
m_pStream->WriteReal(dBorderSizeStyle);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSizeStyle);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dWidth - dBorderSizeStyle * 2, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dHeight - dBorderSizeStyle * 2, 0.0));
}
m_pStream->WriteStr(" re\012W\012n\012");
if (pAnnot && pAnnot->GetWidgetType() == WidgetListbox)
{
CChoiceWidget* pAnnot = dynamic_cast<CChoiceWidget*>(m_pAnnot);
double dBaseLine = pAnnot->GetListBoxHeight();
std::vector<int> arrIndex = pAnnot->GetListBoxIndex();
m_pStream->WriteStr("0.60 0.75 0.85 rg\012");
for (int i = 0; i < arrIndex.size(); ++i)
{
double dH = dHeight - dBorderSizeStyle - dBaseLine * (double)(arrIndex[i] + 1);
if (dH < 0)
break;
m_pStream->WriteReal(dBorderSizeStyle);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dH);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dWidth - dBorderSizeStyle * 2.0, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBaseLine);
m_pStream->WriteStr(" re\012f\012");
}
}
m_pStream->WriteStr("BT\012");
m_dFontSize = std::min(1000.0, std::max(0.0, dFontSize));
if (m_pField)
{
m_pStream->WriteReal(dR);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dG);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dB);
m_pStream->WriteStr(" rg\012");
if (sExtGStateName)
{
m_pStream->WriteEscapeName(sExtGStateName);
m_pStream->WriteStr(" gs\012");
}
m_pStream->WriteEscapeName(pResources->GetFontName(pFont));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(m_dFontSize);
m_pStream->WriteStr(" Tf\012");
}
else
m_pStream->WriteStr(pAnnot->GetDAforAP(pFont).c_str());
m_bStart = true;
m_pFont = pFont;
}
void CAnnotAppearanceObject::StartDraw(const double& dWidth, const double& dHeight)
{
CWidgetAnnotation* pAnnot = dynamic_cast<CWidgetAnnotation*>(m_pAnnot);
if (!m_pStream || !pAnnot)
return;
DrawBackground(dWidth, dHeight);
DrawBorder(dWidth, dHeight);
m_pStream->WriteStr("q\012");
double dBorderSize = pAnnot->GetBorderWidth();
BYTE nType = pAnnot->GetBorderType();
if (nType == 1 || nType == 3)
dBorderSize *= 2;
if (pAnnot->GetWidgetType() == WidgetPushbutton && !((CPushButtonWidget*)pAnnot)->GetRespectBorder())
dBorderSize = 0;
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dWidth - dBorderSize * 2, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dHeight - dBorderSize * 2, 0.0));
m_pStream->WriteStr(" re\012W\012n\012");
if (pAnnot && pAnnot->GetWidgetType() == WidgetListbox)
{
CChoiceWidget* pAnnot = dynamic_cast<CChoiceWidget*>(m_pAnnot);
double dBaseLine = pAnnot->GetListBoxHeight();
std::vector<int> arrIndex = pAnnot->GetListBoxIndex();
m_pStream->WriteStr("0.60 0.75 0.85 rg\012");
for (int i = 0; i < arrIndex.size(); ++i)
{
double dH = dHeight - dBorderSize - dBaseLine * (double)(arrIndex[i] + 1);
if (dH < 0)
break;
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dH);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dWidth - dBorderSize * 2.0, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBaseLine);
m_pStream->WriteStr(" re\012f\012");
}
}
}
void CAnnotAppearanceObject::StartText(CFontDict* pFont, const double& dFontSize)
{
CWidgetAnnotation* pAnnot = dynamic_cast<CWidgetAnnotation*>(m_pAnnot);
if (!m_pStream || !pAnnot)
return;
m_dFontSize = std::min(1000.0, std::max(0.0, dFontSize));
m_pFont = pFont;
m_bStart = true;
m_pStream->WriteStr("BT\012");
m_pStream->WriteStr(pAnnot->GetDAforAP(pFont).c_str());
}
void CAnnotAppearanceObject::DrawPictureInline(const char* sImageName, const double& dX, const double& dY, const double& dW, const double& dH, const bool& bRespectBorder)
{
CWidgetAnnotation* pAnnot = dynamic_cast<CWidgetAnnotation*>(m_pAnnot);
if (!m_pStream || !pAnnot || !sImageName)
return;
m_pStream->WriteStr("q\012");
if (bRespectBorder)
{
TRect oRect = pAnnot->GetRect();
double dWidth = fabs(oRect.fRight - oRect.fLeft);
double dHeight = fabs(oRect.fBottom - oRect.fTop);
double dBorderSize = pAnnot->GetBorderWidth();
BYTE nType = pAnnot->GetBorderType();
if (nType == 1 || nType == 3)
dBorderSize *= 2;
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(fmax(dWidth - 4 * dBorderSize, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(fmax(dHeight - 4 * dBorderSize, 0.0));
m_pStream->WriteStr(" re\012W\012n\012");
}
m_pStream->WriteReal(dW);
m_pStream->WriteStr(" 0 0 ");
m_pStream->WriteReal(dH);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dY);
m_pStream->WriteStr(" cm\012");
m_pStream->WriteEscapeName(sImageName);
m_pStream->WriteStr(" Do\012");
m_pStream->WriteStr("Q\012");
}
void CAnnotAppearanceObject::EndText()
{
m_pStream->WriteStr("ET\012");
}
void CAnnotAppearanceObject::EndDraw()
{
m_pStream->WriteStr("Q\012");
}
void CAnnotAppearanceObject::DrawBackground(const double& dWidth, const double& dHeight)
{
CWidgetAnnotation* pAnnot = dynamic_cast<CWidgetAnnotation*>(m_pAnnot);
if (!pAnnot || !pAnnot->HaveBG())
return;
m_pStream->WriteStr("q\012");
m_pStream->WriteStr(pAnnot->GetBGforAP().c_str());
m_pStream->WriteStr("\012");
m_pStream->WriteStr("1 0 0 1 0 0 cm\012");
m_pStream->WriteStr("0 0 ");
m_pStream->WriteReal(fmax(dWidth, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(fmax(dHeight, 0.0));
m_pStream->WriteStr(" re\012f\012");
m_pStream->WriteStr("Q\012");
}
void CAnnotAppearanceObject::DrawBorder(const double& dWidth, const double& dHeight)
{
CWidgetAnnotation* pAnnot = dynamic_cast<CWidgetAnnotation*>(m_pAnnot);
if (!pAnnot || !pAnnot->HaveBorder())
return;
m_pStream->WriteStr("q\012");
double dBorderSize = pAnnot->GetBorderWidth();
BYTE nType = pAnnot->GetBorderType();
switch (nType)
{
case 1: // Beveled
case 3: // Inset
{
m_pStream->WriteStr(nType == 1 ? "1 g\012" : "0.501953 g\012");
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" m\012");
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight - dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dWidth - dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight - dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dWidth - 2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight - 2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight - 2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteStr("f\012");
if (nType == 1 && pAnnot->HaveBG())
{
m_pStream->WriteStr(pAnnot->GetBGforAP(-0.25).c_str());
m_pStream->WriteStr("\012");
}
else
m_pStream->WriteStr("0.75293 g\012");
m_pStream->WriteReal(dWidth - dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight - dBorderSize);
m_pStream->WriteStr(" m\012");
m_pStream->WriteReal(dWidth - dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dWidth - 2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteReal(dWidth - 2 * dBorderSize);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dHeight - 2 * dBorderSize);
m_pStream->WriteStr(" l\012");
m_pStream->WriteStr("f\012");
break;
}
case 2: // Dashed
{
m_pStream->WriteStr(pAnnot->GetBorderDash().c_str());
break;
}
default: break;
}
m_pStream->WriteStr(pAnnot->GetBCforAP().c_str());
m_pStream->WriteStr("\012");
m_pStream->WriteReal(dBorderSize);
m_pStream->WriteStr(" w\0120 j\0120 J\012");
if (nType == 4) // Underline
{
m_pStream->WriteInt(0);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize / 2);
m_pStream->WriteStr(" m\012");
m_pStream->WriteReal(dWidth);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize / 2);
m_pStream->WriteStr(" l\012S\012");
}
else
{
m_pStream->WriteReal(dBorderSize / 2);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dBorderSize / 2);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dWidth - dBorderSize, 0.0));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(std::max(dHeight - dBorderSize, 0.0));
m_pStream->WriteStr(" re\012S\012");
}
m_pStream->WriteStr("Q\012");
}
void CAnnotAppearanceObject::DrawTextLine(const double& dX, const double& dY, const unsigned short* pCodes, const unsigned int& unCount, CFontCidTrueType** ppFonts, const double* pShifts)
{
CResourcesDict* pResources = dynamic_cast<CResourcesDict*>(Get("Resources"));
if (!pResources)
return;
if (pCodes && pShifts)
{
double _dX = dX + pShifts[0], _dY = dY;
if (!m_bStart)
{
_dX -= m_dCurX;
_dY -= m_dCurY;
m_dCurX += _dX;
m_dCurY += _dY;
}
else
{
m_dCurX = _dX;
m_dCurY = _dY;
}
m_pStream->WriteReal(_dX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(_dY);
m_pStream->WriteStr(" Td\012");
for (unsigned int unIndex = 0; unIndex < unCount; ++unIndex)
{
if (ppFonts)
{
CFontDict* pFont = (CFontDict*)(ppFonts[unIndex]);
if (m_pFont != pFont)
{
m_pStream->WriteEscapeName(pResources->GetFontName((CFontDict*)(ppFonts[unIndex])));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(m_dFontSize);
m_pStream->WriteStr(" Tf\012");
m_pFont = pFont;
}
}
unsigned char unByte[2] = {static_cast<unsigned char>((pCodes[unIndex] >> 8) & 0xFF), static_cast<unsigned char>(pCodes[unIndex] & 0xFF)};
m_pStream->WriteChar('[');
m_pStream->WriteChar('<');
m_pStream->WriteBinary(unByte, 2, NULL);
m_pStream->WriteChar('>');
m_pStream->WriteStr("]TJ\012");
if (unIndex != unCount - 1)
{
m_pStream->WriteReal(pShifts[unIndex + 1]);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(0.0);
m_pStream->WriteStr(" Td\012");
}
}
}
else
{
double _dX = dX, _dY = dY;
if (!m_bStart)
{
_dX -= m_dCurX;
_dY -= m_dCurY;
m_dCurX += _dX;
m_dCurY += _dY;
}
else
{
m_dCurX = _dX;
m_dCurY = _dY;
}
m_pStream->WriteReal(_dX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(_dY);
m_pStream->WriteStr(" Td\012");
for (unsigned int unIndex = 0; unIndex < unCount; ++unIndex)
{
if (ppFonts)
{
CFontDict* pFont = (CFontDict*)(ppFonts[unIndex]);
if (m_pFont != pFont)
{
m_pStream->WriteEscapeName(pResources->GetFontName((CFontDict*)(ppFonts[unIndex])));
m_pStream->WriteChar(' ');
m_pStream->WriteReal(m_dFontSize);
m_pStream->WriteStr(" Tf\012");
m_pFont = pFont;
}
}
unsigned char unByte[2] = {static_cast<unsigned char>((pCodes[unIndex] >> 8) & 0xFF), static_cast<unsigned char>(pCodes[unIndex] & 0xFF)};
m_pStream->WriteChar('<');
m_pStream->WriteBinary(unByte, 2, NULL);
m_pStream->WriteChar('>');
m_pStream->WriteStr(" Tj\012");
}
}
m_bStart = false;
}
void CAnnotAppearanceObject::DrawTextLine(const double &dX, const double &dY, const std::wstring& wsText)
{
m_pStream->WriteReal(dX);
m_pStream->WriteChar(' ');
m_pStream->WriteReal(dY);
m_pStream->WriteStr(" Td\012");
std::string sText = NSFile::CUtf8Converter::GetUtf8StringFromUnicode(wsText);
m_pStream->WriteEscapeText((BYTE*)(sText.c_str()), sText.length());
m_pStream->WriteStr(" Tj\012");
}
void CAnnotAppearanceObject::EndDrawText()
{
m_pStream->WriteStr("ET\012");
m_pStream->WriteStr("Q\012EMC\012");
}
void CAnnotAppearanceObject::DrawTextComment()
{
CArrayObject* pArray = new CArrayObject();
if (!pArray)
return;
Add("BBox", pArray);
pArray->Add(0);
pArray->Add(0);
pArray->Add(20);
pArray->Add(20);
m_pStream->WriteStr("");
}
}