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

4659 lines
124 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 "PdfAnnot.h"
#include "RendererOutputDev.h"
#include "Adaptors.h"
#include "../lib/xpdf/TextString.h"
#include "../lib/xpdf/Link.h"
#include "../lib/xpdf/Annot.h"
#include "../lib/xpdf/GfxFont.h"
#include "../lib/xpdf/Lexer.h"
#include "../lib/xpdf/Parser.h"
#include "../lib/goo/GList.h"
#include "../Resources/BaseFonts.h"
#include "../../DesktopEditor/common/Types.h"
#include "../../DesktopEditor/common/StringExt.h"
#include "../../DesktopEditor/xml/include/xmlutils.h"
#include "../../DesktopEditor/fontengine/ApplicationFonts.h"
#include "../../DesktopEditor/graphics/pro/Fonts.h"
#include <map>
namespace PdfReader
{
double ArrGetNum(Object* pArr, int nI)
{
double dRes = 0.0;
Object oObj;
if (pArr->arrayGet(nI, &oObj)->isNum())
dRes = oObj.getNum();
oObj.free();
return dRes;
}
TextString* getFullFieldName(Object* oField)
{
TextString* sResName = NULL;
if (!oField || !oField->isDict())
return sResName;
Object oName;
if (oField->dictLookup("T", &oName)->isString())
sResName = new TextString(oName.getString());
else
{
oName.free();
return sResName;
}
oName.free();
Object oParent, oParent2;
oField->dictLookup("Parent", &oParent);
int nDepth = 0;
while (oParent.isDict() && nDepth < 50)
{
if (oParent.dictLookup("T", &oName)->isString())
{
if (sResName->getLength())
sResName->insert(0, (Unicode)'.');
sResName->insert(0, oName.getString());
}
oName.free();
oParent.dictLookup("Parent", &oParent2);
oParent.free();
oParent = oParent2;
++nDepth;
}
oParent.free();
return sResName;
}
CAction* getAction(PDFDoc* pdfDoc, Object* oAction)
{
Object oActType;
std::string sSName;
if (oAction->dictLookup("S", &oActType)->isName())
sSName = oActType.getName();
oActType.free();
LinkAction* oAct = LinkAction::parseAction(oAction);
if (!oAct)
return NULL;
CAction* pRes = NULL;
LinkActionKind kind = oAct->getKind();
switch (kind)
{
// Переход внутри файла
case actionGoTo:
{
GString* str = ((LinkGoTo*)oAct)->getNamedDest();
LinkDest* pLinkDest = str ? pdfDoc->findDest(str) : ((LinkGoTo*)oAct)->getDest();
if (!pLinkDest)
break;
CActionGoTo* ppRes = new CActionGoTo();
if (pLinkDest->isPageRef())
{
Ref pageRef = pLinkDest->getPageRef();
ppRes->unPage = pdfDoc->findPage(pageRef.num, pageRef.gen);
}
else
ppRes->unPage = pLinkDest->getPageNum();
if (ppRes->unPage > 0)
--ppRes->unPage;
ppRes->nKind = pLinkDest->getKind();
PDFRectangle* pCropBox = pdfDoc->getCatalog()->getPage(ppRes->unPage + 1)->getCropBox();
double dHeight = pCropBox->y2;
double dX = pCropBox->x1;
switch (ppRes->nKind)
{
case destXYZ:
case destFitH:
case destFitBH:
case destFitV:
case destFitBV:
{
ppRes->unKindFlag = 0;
// 0 - left
if (pLinkDest->getChangeLeft())
{
ppRes->unKindFlag |= (1 << 0);
ppRes->pRect[0] = pLinkDest->getLeft() - dX;
}
// 1 - top
if (pLinkDest->getChangeTop())
{
ppRes->unKindFlag |= (1 << 1);
ppRes->pRect[1] = dHeight - pLinkDest->getTop();
}
// 2 - zoom
if (pLinkDest->getChangeZoom() && pLinkDest->getZoom())
{
ppRes->unKindFlag |= (1 << 2);
ppRes->pRect[2] = pLinkDest->getZoom();
}
break;
}
case destFitR:
{
ppRes->pRect[0] = pLinkDest->getLeft() - dX;
ppRes->pRect[1] = dHeight - pLinkDest->getTop();
ppRes->pRect[2] = pLinkDest->getRight() - dX;
ppRes->pRect[3] = dHeight - pLinkDest->getBottom();
break;
}
case destFit:
case destFitB:
default:
break;
}
if (str)
RELEASEOBJECT(pLinkDest);
pRes = ppRes;
break;
}
// Переход к внешнему файлу
case actionGoToR:
{
break;
}
// Запуск стороннего приложения
case actionLaunch:
{
break;
}
// Внешняя ссылка
case actionURI:
{
CActionURI* ppRes = new CActionURI();
TextString* s = new TextString(((LinkURI*)oAct)->getURI());
ppRes->sURI = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
pRes = ppRes;
break;
}
// Нестандартно именованные действия
case actionNamed:
{
CActionNamed* ppRes = new CActionNamed();
TextString* s = new TextString(((LinkNamed*)oAct)->getName());
ppRes->sNamed = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
pRes = ppRes;
break;
}
// Воспроизведение фильма
case actionMovie:
{
break;
}
// JavaScript
case actionJavaScript:
{
CActionJavaScript* ppRes = new CActionJavaScript();
TextString* s = new TextString(((LinkJavaScript*)oAct)->getJS());
ppRes->sJavaScript = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
pRes = ppRes;
break;
}
// Отправка формы
case actionSubmitForm:
{
break;
}
// Скрытие аннотаций
case actionHide:
{
CActionHide* ppRes = new CActionHide();
ppRes->bHideFlag = ((LinkHide*)oAct)->getHideFlag();
Object* oHideObj = ((LinkHide*)oAct)->getFields();
int nHide = 1, k = 0;
if (oHideObj->isArray())
nHide = oHideObj->arrayGetLength();
Object oHide;
oHideObj->copy(&oHide);
do
{
TextString* s = NULL;
if (oHideObj->isArray())
{
oHide.free();
oHideObj->arrayGet(k, &oHide);
}
if (oHide.isString())
s = new TextString(oHide.getString());
else if (oHide.isDict())
s = getFullFieldName(&oHide);
if (s)
{
std::string sStr = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
ppRes->arrAnnotName.push_back(sStr);
delete s;
}
k++;
} while (k < nHide);
oHide.free();
pRes = ppRes;
break;
}
// Неизвестное действие
case actionUnknown:
default:
{
if (sSName == "ResetForm")
{
CActionResetForm* ppRes = new CActionResetForm();
Object oObj;
if (oAction->dictLookup("Flags", &oObj)->isInt())
ppRes->unFlags = oObj.getInt();
oObj.free();
if (oAction->dictLookup("Fields", &oObj)->isArray())
{
for (int j = 0; j < oObj.arrayGetLength(); ++j)
{
Object oField;
oObj.arrayGet(j, &oField);
TextString* s = NULL;
if (oField.isString())
s = new TextString(oField.getString());
else if (oField.isDict())
s = getFullFieldName(&oField);
if (s)
{
std::string sStr = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
ppRes->arrAnnotName.push_back(sStr);
delete s;
}
oField.free();
}
}
oObj.free();
pRes = ppRes;
}
break;
}
}
if (pRes)
pRes->pNext = NULL;
Object oNextAction;
if (pRes && oAction->dictLookup("Next", &oNextAction)->isDict())
pRes->pNext = getAction(pdfDoc, &oNextAction);
oNextAction.free();
RELEASEOBJECT(oAct);
return pRes;
};
std::string getValue(Object* oV, bool bArray = true)
{
std::string sRes;
if (oV->isName())
sRes = oV->getName();
else if (oV->isString() || oV->isDict() || oV->isArray())
{
TextString* s = NULL;
if (oV->isString())
s = new TextString(oV->getString());
else if (oV->isDict())
{
Object oContents;
if (oV->dictLookup("Contents", &oContents)->isString())
s = new TextString(oContents.getString());
oContents.free();
}
else if (bArray && oV->isArray())
{
Object oContents;
if (oV->arrayGet(0, &oContents)->isString())
s = new TextString(oContents.getString());
oContents.free();
}
if (s)
{
sRes = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
}
return sRes;
}
void DrawAppearance(PDFDoc* pdfDoc, int nPage, AcroFormField* pField, Gfx* gfx, const char* sAPName, const char* sASName)
{
XRef* xref = pdfDoc->getXRef();
Object oFieldRef, oField;
pField->getFieldRef(&oFieldRef);
oFieldRef.fetch(xref, &oField);
Object kidsObj, annotRef, annotObj;
if (oField.dictLookup("Kids", &kidsObj)->isArray())
{
for (int j = 0; j < kidsObj.arrayGetLength(); ++j)
{
kidsObj.arrayGetNF(j, &annotRef);
annotRef.fetch(xref, &annotObj);
pField->drawAnnot(nPage, gfx, gFalse, &annotRef, &annotObj, sAPName, sASName, gFalse);
annotObj.free();
annotRef.free();
}
}
else
pField->drawAnnot(nPage, gfx, gFalse, &oFieldRef, &oField, sAPName, sASName, gFalse);
kidsObj.free();
oFieldRef.free(); oField.free();
}
BYTE getLE(Object* oObj)
{
BYTE nLE = 5; // None
if (oObj->isName("Square"))
nLE = 0;
else if (oObj->isName("Circle"))
nLE = 1;
else if (oObj->isName("Diamond"))
nLE = 2;
else if (oObj->isName("OpenArrow"))
nLE = 3;
else if (oObj->isName("ClosedArrow"))
nLE = 4;
else if (oObj->isName("Butt"))
nLE = 6;
else if (oObj->isName("ROpenArrow"))
nLE = 7;
else if (oObj->isName("RClosedArrow"))
nLE = 8;
else if (oObj->isName("Slash"))
nLE = 9;
return nLE;
}
CAnnotFileAttachment::CEmbeddedFile* getEF(Object* oObj)
{
CAnnotFileAttachment::CEmbeddedFile* pRes = new CAnnotFileAttachment::CEmbeddedFile();
Object oObj2;
Dict* pImDict = oObj->streamGetDict();
if (pImDict->lookup("Length", &oObj2)->isInt())
pRes->nLength = oObj2.getInt();
oObj2.free();
if (pImDict->lookup("DL", &oObj2)->isInt())
pRes->nLength = oObj2.getInt();
oObj2.free();
Stream* pFile = oObj->getStream();
pFile->reset();
pRes->pFile = new BYTE[pRes->nLength];
BYTE* pBufferPtr = pRes->pFile;
for (int nI = 0; nI < pRes->nLength; ++nI)
*pBufferPtr++ = (BYTE)pFile->getChar();
return pRes;
}
GList* tokenize(GString *s)
{
GList *toks;
int i, j;
toks = new GList();
i = 0;
while (i < s->getLength()) {
while (i < s->getLength() && Lexer::isSpace(s->getChar(i))) {
++i;
}
if (i < s->getLength()) {
for (j = i + 1;
j < s->getLength() && !Lexer::isSpace(s->getChar(j));
++j) ;
toks->append(new GString(s, i, j - i));
i = j;
}
}
return toks;
}
CAnnot::CBorderType* getBorder(Object* oBorder, bool bBSorBorder)
{
// Границы и Dash Pattern - Border/BS
CAnnot::CBorderType* pBorderType = new CAnnot::CBorderType();
if (!oBorder)
return pBorderType;
if (bBSorBorder)
{
pBorderType->nType = annotBorderSolid;
Object oV;
if (oBorder->dictLookup("S", &oV)->isName())
{
if (oV.isName("S"))
pBorderType->nType = annotBorderSolid;
else if (oV.isName("D"))
pBorderType->nType = annotBorderDashed;
else if (oV.isName("B"))
pBorderType->nType = annotBorderBeveled;
else if (oV.isName("I"))
pBorderType->nType = annotBorderInset;
else if (oV.isName("U"))
pBorderType->nType = annotBorderUnderlined;
}
oV.free();
if (oBorder->dictLookup("W", &oV)->isNum())
pBorderType->dWidth = oV.getNum();
oV.free();
if (oBorder->dictLookup("D", &oV)->isArray())
{
for (int j = 0; j < oV.arrayGetLength(); ++j)
{
Object oObj2;
if (oV.arrayGet(j, &oObj2)->isNum())
pBorderType->arrDash.push_back(oObj2.getNum());
oObj2.free();
}
}
oV.free();
}
else
{
pBorderType->nType = annotBorderSolid;
pBorderType->dWidth = ArrGetNum(oBorder, 2);
if (!pBorderType->dWidth)
pBorderType->dWidth = 1.0;
Object oObj;
if (oBorder->arrayGetLength() > 3 && oBorder->arrayGet(3, &oObj)->isArray() && oObj.arrayGetLength() > 1)
{
pBorderType->nType = annotBorderDashed;
for (int j = 0; j < oObj.arrayGetLength(); ++j)
{
Object oObj2;
if (oObj.arrayGet(j, &oObj2)->isNum())
pBorderType->arrDash.push_back(oObj2.getNum());
oObj2.free();
}
}
oObj.free();
}
return pBorderType;
}
std::string GetRCFromDS(const std::string& sDS, Object* pContents, const std::vector<double>& arrCFromDA)
{
NSStringUtils::CStringBuilder oRC;
oRC += L"<?xml version=\"1.0\"?><body xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:xfa=\"http://www.xfa.org/schema/xfa-data/1.0/\" xfa:APIVersion=\"Acrobat:23.8.0\" xfa:spec=\"2.0.2\"><p dir=\"ltr\"><span style=\"";
if (sDS.find("font-family") == std::string::npos)
oRC += L"font-family:Helvetica;";
if (sDS.find("font-size") == std::string::npos)
oRC += L"font-size:14.0pt;";
if (sDS.find("text-align") == std::string::npos)
oRC += L"text-align:left;";
if (sDS.find("font-weight") == std::string::npos)
oRC += L"font-weight:normal;";
if (sDS.find("font-style") == std::string::npos)
oRC += L"font-style:normal;";
if (sDS.find("text-decoration") == std::string::npos)
oRC += L"text-decoration:none;";
if (sDS.find("color") == std::string::npos)
{
oRC += L"color:";
if (arrCFromDA.size() == 3)
oRC.WriteHexColor3((unsigned char)(arrCFromDA[0] * 255.0),
(unsigned char)(arrCFromDA[1] * 255.0),
(unsigned char)(arrCFromDA[2] * 255.0));
else
oRC += L"#000000";
}
oRC += (UTF8_TO_U(sDS));
oRC += L"\">";
TextString* s = new TextString(pContents->getString());
std::wstring wsContents = NSStringExt::CConverter::GetUnicodeFromUTF32(s->getUnicode(), s->getLength());
delete s;
oRC.WriteEncodeXmlString(wsContents);
oRC += L"</span></p></body>";
std::wstring wsRC = oRC.GetData();
return U_TO_UTF8(wsRC);
}
//------------------------------------------------------------------------
// Fonts
//------------------------------------------------------------------------
bool CAnnotFonts::IsBaseFont(const std::wstring& wsName)
{
return wsName == L"Courier" || wsName == L"Courier-Bold" || wsName == L"Courier-BoldOblique" || wsName == L"Courier-Oblique" ||
wsName == L"Helvetica" || wsName == L"Helvetica-Bold" || wsName == L"Helvetica-BoldOblique" ||
wsName == L"Helvetica-Oblique" || wsName == L"Symbol" || wsName == L"Times-Bold" || wsName == L"Times-BoldItalic" ||
wsName == L"Times-Italic" || wsName == L"Times-Roman" || wsName == L"ZapfDingbats";
}
std::map<std::wstring, std::wstring> CAnnotFonts::GetAllFonts(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, bool bIsNeedCMap)
{
std::map<std::wstring, std::wstring> mFonts;
AcroForm* pAcroForms = pdfDoc->getCatalog()->getForm();
if (pAcroForms)
{
std::vector<int> arrUniqueFontsRef;
for (int nField = 0, nNum = pAcroForms->getNumFields(); nField < nNum; ++nField)
{
AcroFormField* pField = pAcroForms->getField(nField);
if (!pField)
continue;
// Шрифт и размер шрифта - из DA
Ref fontID;
double dFontSize = 0;
pField->getFont(&fontID, &dFontSize);
Object oFontRef;
if (fontID.num < 0)
{
std::string sFontKey;
if (!GetFontFromAP(pdfDoc, pField, &oFontRef, sFontKey))
{
oFontRef.free();
continue;
}
}
else
oFontRef.initRef(fontID.num, fontID.gen);
if (std::find(arrUniqueFontsRef.begin(), arrUniqueFontsRef.end(), oFontRef.getRefNum()) != arrUniqueFontsRef.end())
{
oFontRef.free();
continue;
}
std::string sFontName;
std::string sActualFontName;
std::wstring wsFileName;
bool bBold = false, bItalic = false;
wsFileName = GetFontData(pdfDoc, pFontManager, pFontList, &oFontRef, sFontName, sActualFontName, bBold, bItalic, bIsNeedCMap);
if (!sActualFontName.empty())
{
oFontRef.free();
continue;
}
if (!sFontName.empty())
{
std::wstring wsFontName = UTF8_TO_U(sFontName);
if (mFonts.find(wsFontName) == mFonts.end())
{
arrUniqueFontsRef.push_back(oFontRef.getRefNum());
mFonts[wsFontName] = wsFileName;
}
}
oFontRef.free();
if (pField->getAcroFormFieldType() == acroFormFieldPushbutton && fontID.num >= 0)
{
std::string sFontKey;
if (GetFontFromAP(pdfDoc, pField, &oFontRef, sFontKey) && std::find(arrUniqueFontsRef.begin(), arrUniqueFontsRef.end(), oFontRef.getRefNum()) == arrUniqueFontsRef.end())
{
wsFileName = GetFontData(pdfDoc, pFontManager, pFontList, &oFontRef, sFontName, sActualFontName, bBold, bItalic, bIsNeedCMap);
std::wstring wsFontName = UTF8_TO_U(sFontName);
if (sActualFontName.empty() && mFonts.find(wsFontName) == mFonts.end())
{
arrUniqueFontsRef.push_back(oFontRef.getRefNum());
mFonts[wsFontName] = wsFileName;
}
}
}
oFontRef.free();
}
}
for (int nPage = 0, nLastPage = pdfDoc->getNumPages(); nPage < nLastPage; ++nPage)
{
Page* pPage = pdfDoc->getCatalog()->getPage(nPage + 1);
if (!pPage)
continue;
Object oAnnots;
if (!pPage->getAnnots(&oAnnots)->isArray())
{
oAnnots.free();
continue;
}
for (int i = 0, nNum = oAnnots.arrayGetLength(); i < nNum; ++i)
{
Object oAnnot;
if (!oAnnots.arrayGet(i, &oAnnot)->isDict())
{
oAnnot.free();
continue;
}
Object oSubtype;
if (!oAnnot.dictLookup("Subtype", &oSubtype)->isName("FreeText"))
{
oSubtype.free(); oAnnot.free();
continue;
}
oSubtype.free();
std::string sRC;
Object oObj;
if (!oAnnot.dictLookup("RC", &oObj)->isString())
{
oObj.free();
if (oAnnot.dictLookup("Contents", &oObj)->isString() && oObj.getString()->getLength())
{
std::string sDS;
Object oObj2;
if (oAnnot.dictLookup("DS", &oObj2)->isString())
{
TextString* s = new TextString(oObj2.getString());
sDS = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj2.free();
sRC = GetRCFromDS(sDS, &oObj, {});
if (sRC.find("font-family:Helvetica") != std::string::npos)
{
const unsigned char* pData14 = NULL;
unsigned int nSize14 = 0;
std::wstring wsFontName = L"Helvetica";
NSFonts::IFontsMemoryStorage* pMemoryStorage = NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage();
if (pMemoryStorage && !pMemoryStorage->Get(wsFontName) && GetBaseFont(wsFontName, pData14, nSize14))
pMemoryStorage->Add(wsFontName, (BYTE*)pData14, nSize14, false);
mFonts[L"Helvetica"] = L"Helvetica";
}
}
}
else
{
TextString* s = new TextString(oObj.getString());
sRC = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free(); oAnnot.free();
Object oAnnotRef;
oAnnots.arrayGetNF(i, &oAnnotRef);
std::vector<PdfReader::CAnnotMarkup::CFontData*> arrRC = CAnnotMarkup::ReadRC(sRC);
std::map<std::wstring, std::wstring> mFreeText = GetFreeTextFont(pdfDoc, pFontManager, pFontList, &oAnnotRef, arrRC);
for (std::map<std::wstring, std::wstring>::iterator it = mFreeText.begin(); it != mFreeText.end(); ++it)
{
if (mFonts.find(it->first) != mFonts.end())
continue;
mFonts[it->first] = it->second;
}
oAnnotRef.free();
for (int j = 0; j < arrRC.size(); ++j)
RELEASEOBJECT(arrRC[j]);
}
oAnnots.free();
}
return mFonts;
}
std::wstring CAnnotFonts::GetFontData(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oFontRef, std::string& sFontName, std::string& sActualFontName, bool& bBold, bool& bItalic, bool bIsNeedCMap)
{
bBold = false, bItalic = false;
XRef* xref = pdfDoc->getXRef();
Object oFont;
if (!xref->fetch(oFontRef->getRefNum(), oFontRef->getRefGen(), &oFont)->isDict())
{
oFont.free();
return L"";
}
GfxFont* gfxFont = GfxFont::makeFont(xref, "F", oFontRef->getRef(), oFont.getDict());
oFont.free();
if (!gfxFont)
return L"";
Ref oEmbRef;
std::wstring wsFontBaseName = NSStrings::GetStringFromUTF32(gfxFont->getName());
std::wstring wsFileName;
if (gfxFont->getEmbeddedFontID(&oEmbRef) || IsBaseFont(wsFontBaseName))
{
std::wstring wsFontName;
RendererOutputDev::GetFont(xref, pFontManager, pFontList, gfxFont, wsFileName, wsFontName);
sFontName = U_TO_UTF8(wsFontName);
RendererOutputDev::CheckFontStylePDF(wsFontName, bBold, bItalic);
if (!bBold)
bBold = gfxFont->isBold();
if (!bItalic)
bItalic = gfxFont->isItalic();
}
else
{
std::wstring wsFBN = wsFontBaseName;
NSFonts::CFontInfo* pFontInfo = RendererOutputDev::GetFontByParams(xref, pFontManager, gfxFont, wsFBN);
if (pFontInfo && !pFontInfo->m_wsFontPath.empty())
{
if (wsFontBaseName.length() > 7 && wsFontBaseName.at(6) == '+')
{
bool bIsRemove = true;
for (int nIndex = 0; nIndex < 6; nIndex++)
{
wchar_t nChar = wsFontBaseName.at(nIndex);
if (nChar < 'A' || nChar > 'Z')
{
bIsRemove = false;
break;
}
}
if (bIsRemove)
wsFontBaseName.erase(0, 7);
}
wsFileName = pFontInfo->m_wsFontPath;
sFontName = U_TO_UTF8(wsFontBaseName);
sActualFontName = U_TO_UTF8(pFontInfo->m_wsFontName);
bBold = pFontInfo->m_bBold;
bItalic = pFontInfo->m_bItalic;
}
}
RELEASEOBJECT(gfxFont);
return wsFileName;
}
bool CAnnotFonts::GetFontFromAP(PDFDoc* pdfDoc, AcroFormField* pField, Object* oFontRef, std::string& sFontKey)
{
bool bFindResources = false;
Object oAP, oN;
XRef* xref = pdfDoc->getXRef();
if (pField->fieldLookup("AP", &oAP)->isDict() && oAP.dictLookup("N", &oN)->isStream())
{
Parser* parser = new Parser(xref, new Lexer(xref, &oN), gFalse);
bool bFindFont = false;
Object oObj1, oObj2, oObj3;
parser->getObj(&oObj1);
while (!oObj1.isEOF())
{
if (oObj1.isName())
{
parser->getObj(&oObj2);
if (oObj2.isEOF())
break;
if (oObj2.isNum())
{
parser->getObj(&oObj3);
if (oObj3.isEOF())
break;
if (oObj3.isCmd("Tf"))
{
bFindFont = true;
break;
}
}
}
if (oObj2.isName())
{
oObj1.free();
oObj2.copy(&oObj1);
oObj2.free(); oObj3.free();
continue;
}
if (oObj3.isName())
{
oObj1.free();
oObj3.copy(&oObj1);
oObj3.free(); oObj2.free();
continue;
}
oObj1.free(); oObj2.free(); oObj3.free();
parser->getObj(&oObj1);
}
if (bFindFont && oObj1.isName())
{
Object oR, oFonts;
bFindResources = oN.streamGetDict()->lookup("Resources", &oR)->isDict() && oR.dictLookup("Font", &oFonts)->isDict() && oFonts.dictLookupNF(oObj1.getName(), oFontRef)->isRef();
sFontKey = oObj1.getName();
oR.free(); oFonts.free();
}
oObj1.free(); oObj2.free(); oObj3.free();
RELEASEOBJECT(parser);
}
oAP.free(); oN.free();
return bFindResources;
}
bool CAnnotFonts::FindFonts(Object* oStream, int nDepth, Object* oResFonts)
{
if (nDepth > 5)
return false;
Object oResources;
if (!oStream->streamGetDict()->lookup("Resources", &oResources)->isDict())
{
oResources.free();
return false;
}
if (oResources.dictLookup("Font", oResFonts)->isDict())
{
oResources.free();
return true;
}
Object oXObject;
if (oResources.dictLookup("XObject", &oXObject)->isDict())
{
for (int i = 0, nLength = oXObject.dictGetLength(); i < nLength; ++i)
{
Object oXObj;
if (!oXObject.dictGetVal(i, &oXObj)->isStream())
{
oXObj.free();
continue;
}
if (FindFonts(&oXObj, nDepth + 1, oResFonts))
{
oXObj.free(); oXObject.free(); oResources.free();
return true;
}
oXObj.free();
}
}
oXObject.free(); oResources.free();
return false;
}
std::map<std::wstring, std::wstring> CAnnotFonts::GetAnnotFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef)
{
Object oAnnot, oObj;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
std::map<std::wstring, std::wstring> mFontFreeText;
Object oAP, oN;
if (!oAnnot.dictLookup("AP", &oAP)->isDict() || !oAP.dictLookup("N", &oN)->isStream())
{
oAP.free(); oN.free(); oAnnot.free();
return mFontFreeText;
}
oAP.free();
Object oFonts;
if (!FindFonts(&oN, 0, &oFonts))
{
oN.free(); oFonts.free(); oAnnot.free();
return mFontFreeText;
}
oN.free();
CFontList* pAppFontList = (CFontList*)pFontManager->GetApplication()->GetList();
NSFonts::IFontsMemoryStorage* pMemoryStorage = NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage();
for (int i = 0, nFonts = oFonts.dictGetLength(); i < nFonts; ++i)
{
Object oFontRef;
if (!oFonts.dictGetValNF(i, &oFontRef)->isRef())
{
oFontRef.free();
continue;
}
std::string sFontName, sActualFontName;
bool bBold = false, bItalic = false;
std::wstring sFontPath = GetFontData(pdfDoc, pFontManager, pFontList, &oFontRef, sFontName, sActualFontName, bBold, bItalic);
oFontRef.free();
if (sFontPath.empty() || IsBaseFont(sFontPath) || !sActualFontName.empty())
continue;
std::wstring wsFontName = UTF8_TO_U(sFontName);
NSFonts::IFontStream* pFontStream = NULL;
bool bRemoveStream = false;
if (pMemoryStorage)
pFontStream = (NSFonts::IFontStream*)pMemoryStorage->Get(sFontPath);
else
{
pFontStream = NSFonts::NSStream::Create();
pFontStream->CreateFromFile(sFontPath);
bRemoveStream = true;
}
if (pFontStream)
{
bool bNew = true;
std::vector<NSFonts::CFontInfo*>* arrFontList = pAppFontList->GetFonts();
for (int nIndex = 0; nIndex < arrFontList->size(); ++nIndex)
{
if (((*arrFontList)[nIndex]->m_wsFontPath == sFontPath ||
(*arrFontList)[nIndex]->m_wsFontName == wsFontName) &&
(*arrFontList)[nIndex]->m_bBold == (bBold ? 1 : 0) &&
(*arrFontList)[nIndex]->m_bItalic == (bItalic ? 1 : 0))
{
bNew = false;
break;
}
}
if (bNew)
pAppFontList->Add(sFontPath, pFontStream);
}
if (bRemoveStream)
RELEASEINTERFACE(pFontStream);
mFontFreeText[wsFontName] = sFontPath;
}
oFonts.free(); oAnnot.free();
return mFontFreeText;
}
std::map<std::wstring, std::wstring> CAnnotFonts::GetFreeTextFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, Object* oAnnotRef, std::vector<CAnnotMarkup::CFontData*>& arrRC)
{
std::map<std::wstring, std::wstring> mRes;
std::map<std::wstring, std::wstring> mFontFreeText = GetAnnotFont(pdfDoc, pFontManager, pFontList, oAnnotRef);
CFontList* pAppFontList = (CFontList*)pFontManager->GetApplication()->GetList();
for (int i = 0; i < arrRC.size(); ++i)
{
if (arrRC[i]->bFind)
continue;
std::string sFontName = arrRC[i]->sFontFamily;
std::wstring wsFontName = UTF8_TO_U(sFontName);
bool bBold = (bool)((arrRC[i]->unFontFlags >> 0) & 1);
bool bItalic = (bool)((arrRC[i]->unFontFlags >> 1) & 1);
if (IsBaseFont(wsFontName))
{
if (sFontName == "Times-Roman")
{
if (bBold && bItalic)
sFontName = "Times-BoldItalic";
else if (bBold)
sFontName = "Times-Bold";
else if (bItalic)
sFontName = "Times-Italic";
}
else if (sFontName == "Courier" || sFontName == "Helvetica")
{
if (bBold && bItalic)
sFontName += "-BoldOblique";
else if (bBold)
sFontName += "-Bold";
else if (bItalic)
sFontName += "-Oblique";
}
wsFontName = UTF8_TO_U(sFontName);
const unsigned char* pData14 = NULL;
unsigned int nSize14 = 0;
NSFonts::IFontsMemoryStorage* pMemoryStorage = NSFonts::NSApplicationFontStream::GetGlobalMemoryStorage();
if (pMemoryStorage && !pMemoryStorage->Get(wsFontName) && GetBaseFont(wsFontName, pData14, nSize14))
pMemoryStorage->Add(wsFontName, (BYTE*)pData14, nSize14, false);
std::string sFontNameBefore = arrRC[i]->sFontFamily;
arrRC[i]->sFontFamily = sFontName;
arrRC[i]->bFind = true;
mRes[wsFontName] = wsFontName;
for (int j = i; j < arrRC.size(); ++j)
{
if (arrRC[j]->sFontFamily == sFontNameBefore && bBold == (bool)((arrRC[j]->unFontFlags >> 0) & 1) && bItalic == (bool)((arrRC[j]->unFontFlags >> 1) & 1))
{
arrRC[j]->sFontFamily = sFontName;
arrRC[j]->bFind = true;
}
}
}
else
{
NSFonts::CFontSelectFormat oFontSelect;
if (bBold)
oFontSelect.bBold = new INT(1);
if (bItalic)
oFontSelect.bItalic = new INT(1);
oFontSelect.wsName = new std::wstring(wsFontName);
NSFonts::CFontInfo* pFontInfo = pAppFontList->GetByParams(oFontSelect);
if (pFontInfo && !pFontInfo->m_wsFontPath.empty())
{
std::wstring sFontPath = pFontInfo->m_wsFontPath;
bool bFindFreeText = false;
for (std::map<std::wstring, std::wstring>::iterator it = mFontFreeText.begin(); it != mFontFreeText.end(); ++it)
{
if (it->second == sFontPath)
{
bFindFreeText = true;
break;
}
}
std::wstring wsFontBaseName = pFontInfo->m_wsFontName;
if (wsFontBaseName.length() > 7 && wsFontBaseName.at(6) == '+')
{
bool bIsRemove = true;
for (int nIndex = 0; nIndex < 6; nIndex++)
{
wchar_t nChar = wsFontBaseName.at(nIndex);
if (nChar < 'A' || nChar > 'Z')
{
bIsRemove = false;
break;
}
}
if (bIsRemove)
wsFontBaseName.erase(0, 7);
}
if (bFindFreeText)
{
arrRC[i]->sFontFamily = U_TO_UTF8(wsFontBaseName);
mRes[wsFontBaseName] = pFontInfo->m_wsFontPath;
}
else
{
arrRC[i]->unFontFlags |= (1 << 6);
arrRC[i]->sActualFont = U_TO_UTF8(wsFontBaseName);
}
arrRC[i]->bFind = true;
std::string sFontNameNew = bFindFreeText ? arrRC[i]->sFontFamily : arrRC[i]->sActualFont;
for (int j = i; j < arrRC.size(); ++j)
{
if (arrRC[j]->sFontFamily == sFontName && bBold == (bool)((arrRC[j]->unFontFlags >> 0) & 1) && bItalic == (bool)((arrRC[j]->unFontFlags >> 1) & 1))
{
if (bFindFreeText)
arrRC[j]->sFontFamily = sFontNameNew;
else
{
arrRC[j]->unFontFlags |= (1 << 6);
arrRC[j]->sActualFont = sFontNameNew;
}
arrRC[j]->bFind = true;
}
}
}
}
}
return mRes;
}
//------------------------------------------------------------------------
// Widget
//------------------------------------------------------------------------
CAnnotWidgetBtn::CAnnotWidgetBtn(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefID) : CAnnotWidget(pdfDoc, pField, nStartRefID)
{
m_unIFFlag = 0;
Object oObj;
Object oFieldRef, oField;
pField->getFieldRef(&oFieldRef);
oFieldRef.fetch(pdfDoc->getXRef(), &oField);
oFieldRef.free();
// 9 - Значение поля - V
if (oField.dictLookup("V", &oObj))
{
m_sV = getValue(&oObj);
if (!m_sV.empty())
m_unFlags |= (1 << 9);
}
oObj.free();
oField.free();
if (pField->fieldLookup("AS", &oObj)->isName())
{
m_sV = oObj.getName();
m_unFlags |= (1 << 9);
}
oObj.free();
Object oMK;
AcroFormFieldType oType = pField->getAcroFormFieldType();
m_nStyle = (oType == acroFormFieldRadioButton ? 3 : 0);
if (pField->fieldLookup("MK", &oMK)->isDict())
{
if (oType == acroFormFieldPushbutton)
{
// 10 - Заголовок - СА
m_sCA = DictLookupString(&oMK, "CA", 10);
// 11 - Заголовок прокрутки - RC
m_sRC = DictLookupString(&oMK, "RC", 11);
// 12 - Альтернативный заголовок - AC
m_sAC = DictLookupString(&oMK, "AC", 12);
}
else
{
if (oMK.dictLookup("CA", &oObj)->isString())
{
std::string sCA(oObj.getString()->getCString());
if (sCA == "l") // кружок
m_nStyle = 3;
else if (sCA == "4") // галка
m_nStyle = 0;
else if (sCA == "8") // крест
m_nStyle = 1;
else if (sCA == "u") // ромб
m_nStyle = 2;
else if (sCA == "n") // квадрат
m_nStyle = 5;
else if (sCA == "H") // звезда
m_nStyle = 4;
}
oObj.free();
}
// 13 - Положение заголовка - TP
if (oMK.dictLookup("TP", &oObj)->isInt())
{
m_nTP = oObj.getInt();
m_unFlags |= (1 << 13);
}
oObj.free();
Object oIF;
if (oMK.dictLookup("IF", &oIF)->isDict())
{
m_unIFFlag = 1;
// 1 - Масштабирование - SW
if (oIF.dictLookup("SW", &oObj)->isName())
{
m_unIFFlag |= (1 << 1);
std::string sName(oObj.getName());
m_nSW = 0; // Default: A
if (sName == "B")
m_nSW = 2;
else if (sName == "S")
m_nSW = 3;
else if (sName == "N")
m_nSW = 1;
}
oObj.free();
// 2 - Тип масштабирования - S
if (oIF.dictLookup("S", &oObj)->isName())
{
m_unIFFlag |= (1 << 2);
std::string sName(oObj.getName());
m_nS = 0; // Default: P
if (sName == "A")
m_nS = 1;
}
oObj.free();
// 3 - Смещение - A
if (oIF.dictLookup("A", &oObj)->isArray())
{
m_dA1 = 0.5, m_dA2 = 0.5;
Object oObj2;
m_unIFFlag |= (1 << 3);
m_dA1 = ArrGetNum(&oObj, 0);
m_dA2 = ArrGetNum(&oObj, 1);
}
oObj.free();
// 4 - Полное соответствие - FB
if (oIF.dictLookup("FB", &oObj)->isBool() && oObj.getBool())
m_unIFFlag |= (1 << 4);
oObj.free();
}
oIF.free();
}
oMK.free();
Object oOpt;
pField->fieldLookup("Opt", &oOpt);
// 14 - Имя вкл состояния - AP - N - Yes
Object oNorm;
if (pField->fieldLookup("AP", &oObj)->isDict() && oObj.dictLookup("N", &oNorm)->isDict() && oOpt.isNull())
{
for (int j = 0, nNormLength = oNorm.dictGetLength(); j < nNormLength; ++j)
{
std::string sNormName(oNorm.dictGetKey(j));
if (sNormName != "Off")
{
m_unFlags |= (1 << 14);
m_sAP_N_Yes = sNormName;
break;
}
}
}
oNorm.free(); oObj.free(); oOpt.free();
}
CAnnotWidgetTx::CAnnotWidgetTx(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefID) : CAnnotWidget(pdfDoc, pField, nStartRefID)
{
Object oObj;
Object oFieldRef, oField;
pField->getFieldRef(&oFieldRef);
oFieldRef.fetch(pdfDoc->getXRef(), &oField);
oFieldRef.free();
// 9 - Значение - V
if (oField.dictLookup("V", &oObj))
{
m_sV = getValue(&oObj);
if (!m_sV.empty())
m_unFlags |= (1 << 9);
}
oObj.free();
oField.free();
// 10 - Максимальное количество символов в Tx - MaxLen
if (oField.dictLookup("MaxLen", &oObj)->isInt())
{
m_unFlags |= (1 << 10);
m_unMaxLen = oObj.getInt();
}
oObj.free();
// 11 - Расширенный текст RV - RichText
if (pField->getFlags() & (1 << 25))
m_sRV = FieldLookupString(pField, "RV", 11);
}
CAnnotWidgetCh::CAnnotWidgetCh(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefID) : CAnnotWidget(pdfDoc, pField, nStartRefID)
{
Object oObj;
Object oFieldRef, oField;
pField->getFieldRef(&oFieldRef);
oFieldRef.fetch(pdfDoc->getXRef(), &oField);
oFieldRef.free();
// 9 - Значение
if (oField.dictLookup("V", &oObj))
{
m_sV = getValue(&oObj, false);
if (!m_sV.empty())
m_unFlags |= (1 << 9);
}
oObj.free();
Object oOpt;
// 10 - Список значений
if (oField.dictLookup("Opt", &oOpt)->isArray())
{
m_unFlags |= (1 << 10);
int nOptLength = oOpt.arrayGetLength();
for (int j = 0; j < nOptLength; ++j)
{
Object oOptJ;
if (!oOpt.arrayGet(j, &oOptJ) || !(oOptJ.isString() || oOptJ.isArray()))
{
oOptJ.free();
continue;
}
std::string sOpt1, sOpt2;
if (oOptJ.isArray() && oOptJ.arrayGetLength() > 1)
{
Object oOptJ2;
if (oOptJ.arrayGet(0, &oOptJ2)->isString())
{
TextString* s = new TextString(oOptJ2.getString());
sOpt1 = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oOptJ2.free();
if (oOptJ.arrayGet(1, &oOptJ2)->isString())
{
TextString* s = new TextString(oOptJ2.getString());
sOpt2 = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oOptJ2.free();
}
else if (oOptJ.isString())
{
TextString* s = new TextString(oOptJ.getString());
sOpt2 = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
m_arrOpt.push_back(std::make_pair(sOpt1, sOpt2));
oOptJ.free();
}
}
oOpt.free();
// 11 - Индекс верхнего элемента - TI
if (pField->fieldLookup("TI", &oObj)->isInt())
{
m_unFlags |= (1 << 11);
m_unTI = oObj.getInt();
}
oObj.free();
// 12 - Выбранные индексы - I
if (oField.dictLookup("I", &oOpt)->isArray())
{
m_unFlags |= (1 << 12);
for (int j = 0; j < oOpt.arrayGetLength(); ++j)
{
if (oOpt.arrayGet(j, &oObj)->isInt())
m_arrI.push_back(oObj.getInt());
oObj.free();
}
}
oOpt.free();
// 13 - Массив значений
if (oField.dictLookup("V", &oOpt)->isArray())
{
m_unFlags |= (1 << 13);
int nVLength = oOpt.arrayGetLength();
for (int j = 0; j < nVLength; ++j)
{
if (oOpt.arrayGet(j, &oObj)->isString())
{
TextString* s = new TextString(oObj.getString());
m_arrV.push_back(NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength()));
delete s;
}
oObj.free();
}
}
oOpt.free();
oField.free();
}
CAnnotWidgetSig::CAnnotWidgetSig(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefID) : CAnnotWidget(pdfDoc, pField, nStartRefID)
{
Object oObj;
Object oFieldRef, oField;
pField->getFieldRef(&oFieldRef);
oFieldRef.fetch(pdfDoc->getXRef(), &oField);
oFieldRef.free();
// 9 - Значение
if (oField.dictLookup("V", &oObj)->isDict())
m_unFlags |= (1 << 9);
oObj.free();
oField.free();
}
CAnnotWidget::CAnnotWidget(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefID) : CAnnot(pdfDoc, pField, nStartRefID)
{
Object oObj, oField;
XRef* xref = pdfDoc->getXRef();
pField->getFieldRef(&oObj);
oObj.fetch(xref, &oField);
oObj.free();
m_bChangeFullName = false;
m_dFontSize = 0.0;
m_unFontStyle = 0;
// Цвет текста - из DA
int nSpace;
GList *arrColors = pField->getColorSpace(&nSpace);
for (int j = 0; j < nSpace; ++j)
m_arrTC.push_back(*(double*)arrColors->get(j));
deleteGList(arrColors, double);
// Выравнивание текста - Q
m_nQ = 0;
if (pField->fieldLookup("Q", &oObj)->isInt())
m_nQ = oObj.getInt();
oObj.free();
// Тип - FT + флаги
AcroFormFieldType oType = pField->getAcroFormFieldType();
m_nType = 26; // Unknown
switch (oType)
{
case acroFormFieldPushbutton: m_nType = 27; break;
case acroFormFieldRadioButton: m_nType = 28; break;
case acroFormFieldCheckbox: m_nType = 29; break;
case acroFormFieldFileSelect: m_nType = 30; break;
case acroFormFieldMultilineText: m_nType = 30; break;
case acroFormFieldText: m_nType = 30; break;
case acroFormFieldBarcode: m_nType = 30; break;
case acroFormFieldComboBox: m_nType = 31; break;
case acroFormFieldListBox: m_nType = 32; break;
case acroFormFieldSignature: m_nType = 33; break;
default: m_nType = 26; break;
}
// Флаг - Ff
m_unFieldFlag = -1;
if (oField.dictLookup("Ff", &oObj)->isInt())
m_unFieldFlag = oObj.getInt();
oObj.free();
// 0 - Альтернативное имя поля, используется во всплывающей подсказке и сообщениях об ошибке - TU
if (oField.dictLookup("TU", &oObj))
{
m_sTU = getValue(&oObj);
if (!m_sTU.empty())
m_unFlags |= (1 << 0);
}
oObj.free();
// 1 - Строка стиля по умолчанию - DS
m_sDS = FieldLookupString(pField, "DS", 1);
// 3 - Режим выделения - H
if (pField->fieldLookup("H", &oObj)->isName())
{
m_unFlags |= (1 << 3);
std::string sName(oObj.getName());
m_nH = 1; // Default: I
if (sName == "N")
m_nH = 0;
else if (sName == "O")
m_nH = 3;
else if (sName == "P" || sName == "T")
m_nH = 2;
}
oObj.free();
Object oMK;
if (pField->fieldLookup("MK", &oMK)->isDict())
{
// 5 - Цвет границ - BC. Даже если граница не задана BS/Border, то при наличии BC предоставляется граница по-умолчанию (сплошная, толщиной 1)
if (oMK.dictLookup("BC", &oObj)->isArray())
{
m_unFlags |= (1 << 5);
int nBCLength = oObj.arrayGetLength();
for (int j = 0; j < nBCLength; ++j)
{
Object oBCj;
m_arrBC.push_back(oObj.arrayGet(j, &oBCj)->isNum() ? oBCj.getNum() : 0.0);
oBCj.free();
}
}
oObj.free();
// 6 - Поворот аннотации относительно страницы - R
if (oMK.dictLookup("R", &oObj)->isInt())
{
m_unFlags |= (1 << 6);
m_unR = oObj.getInt();
}
oObj.free();
// 7 - Цвет фона - BG
if (oMK.dictLookup("BG", &oObj)->isArray())
{
m_unFlags |= (1 << 7);
int nBGLength = oObj.arrayGetLength();
for (int j = 0; j < nBGLength; ++j)
{
Object oBGj;
m_arrBG.push_back(oObj.arrayGet(j, &oBGj)->isNum() ? oBGj.getNum() : 0.0);
oBGj.free();
}
}
oObj.free();
}
oMK.free();
// 8 - Значение по-умолчанию
if (oField.dictLookup("DV", &oObj))
{
m_sDV = getValue(&oObj);
if (!m_sDV.empty())
m_unFlags |= (1 << 8);
}
oObj.free();
// 17 - Родитель - Parent
m_unRefNumParent = 0;
if (oField.dictLookupNF("Parent", &oObj)->isRef())
{
m_unRefNumParent = oObj.getRefNum() + nStartRefID;
m_unFlags |= (1 << 17);
}
oObj.free();
// 18 - Частичное имя поля - T
m_sT = DictLookupString(&oField, "T", 18);
m_sFullName = m_sT;
// 21 - MEOptions
if (oField.dictLookup("MEOptions", &oObj)->isInt())
{
m_unFlags |= (1 << 21);
m_unMEOptions = oObj.getInt();
}
oObj.free();
// Action - A
Object oAction;
if (oField.dictLookup("A", &oAction)->isDict())
{
std::string sAA = "A";
CAction* pA = getAction(pdfDoc, &oAction);
if (pA)
{
pA->sType = sAA;
m_arrAction.push_back(pA);
}
}
oAction.free();
// Actions - AA
Object oAA;
if (oField.dictLookup("AA", &oAA)->isDict())
{
for (int j = 0; j < oAA.dictGetLength(); ++j)
{
if (oAA.dictGetVal(j, &oAction)->isDict())
{
std::string sAA(oAA.dictGetKey(j));
CAction* pA = getAction(pdfDoc, &oAction);
if (pA)
{
pA->sType = sAA;
m_arrAction.push_back(pA);
}
}
oAction.free();
}
}
oAA.free();
oField.free();
}
CAnnotWidget::~CAnnotWidget()
{
ClearActions();
}
std::string CAnnotWidget::FieldLookupString(AcroFormField* pField, const char* sName, int nByte)
{
std::string sRes;
Object oObj;
if (pField->fieldLookup(sName, &oObj)->isString())
{
m_unFlags |= (1 << nByte);
TextString* s = new TextString(oObj.getString());
sRes = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
return sRes;
}
void CAnnotWidget::SetFont(PDFDoc* pdfDoc, AcroFormField* pField, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList)
{
// Шрифт и размер шрифта - из DA
Ref fontID;
pField->getFont(&fontID, &m_dFontSize);
m_unFontStyle = 0;
Object oFontRef;
if (fontID.num < 0)
{
if (!CAnnotFonts::GetFontFromAP(pdfDoc, pField, &oFontRef, m_sFontKey))
{
oFontRef.free();
return;
}
}
else
oFontRef.initRef(fontID.num, fontID.gen);
bool bBold = false, bItalic = false;
CAnnotFonts::GetFontData(pdfDoc, pFontManager, pFontList, &oFontRef, m_sFontName, m_sActualFontName, bBold, bItalic);
oFontRef.free();
// 2 - Актуальный шрифт
if (!m_sActualFontName.empty())
m_unFlags |= (1 << 2);
// 4 - Уникальный идентификатор шрифта
if (!m_sFontKey.empty())
m_unFlags |= (1 << 4);
if (bBold)
m_unFontStyle |= (1 << 0);
if (bItalic)
m_unFontStyle |= (1 << 1);
}
void CAnnotWidget::SetButtonFont(PDFDoc* pdfDoc, AcroFormField* pField, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList)
{
// Неполный шрифт во внешнем виде pushbutton
Object oFontRef;
if (!CAnnotFonts::GetFontFromAP(pdfDoc, pField, &oFontRef, m_sFontKey))
{
oFontRef.free();
return;
}
bool bBold = false, bItalic = false;
CAnnotFonts::GetFontData(pdfDoc, pFontManager, pFontList, &oFontRef, m_sButtonFontName, m_sButtonFontName, bBold, bItalic);
if (!m_sButtonFontName.empty())
m_unFlags |= (1 << 19);
oFontRef.free();
}
bool CAnnotWidget::ChangeFullName(const std::string& sPrefixForm)
{
m_bChangeFullName = true;
if (m_unFlags & (1 << 18))
{
m_sT += sPrefixForm;
m_sFullName += sPrefixForm;
return true;
}
return false;
}
void CAnnotWidget::ClearActions()
{
for (int i = 0; i < m_arrAction.size(); ++i)
RELEASEOBJECT(m_arrAction[i]);
m_arrAction.clear();
}
//------------------------------------------------------------------------
// Popup
//------------------------------------------------------------------------
CAnnotPopup::CAnnotPopup(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnot(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
m_unFlags = 0;
Object oAnnot, oObj;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// 0 - Отображаться открытой - Open
if (oAnnot.dictLookup("Open", &oObj)->isBool() && oObj.getBool())
m_unFlags |= (1 << 0);
oObj.free();
// 1 - Родитель - Parent
if (oAnnot.dictLookupNF("Parent", &oObj)->isRef())
{
m_unFlags |= (1 << 1);
m_unRefNumParent = oObj.getRefNum() + nStartRefID;
}
oObj.free();
oAnnot.free();
}
//------------------------------------------------------------------------
// Text
//------------------------------------------------------------------------
CAnnotText::CAnnotText(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
Object oAnnot, oObj;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// 15 - Отображаться открытой - Open
if (oAnnot.dictLookup("Open", &oObj)->isBool() && oObj.getBool())
m_unFlags |= (1 << 15);
oObj.free();
// 16 - Иконка - Name
m_unFlags |= (1 << 16);
m_nName = 10; // Default: Note
if (oAnnot.dictLookup("Name", &oObj)->isName())
{
std::string sName(oObj.getName());
std::vector<std::string> arrName = {"Check", "Checkmark", "Circle", "Comment", "Cross", "CrossHairs", "Help", "Insert", "Key", "NewParagraph", "Note", "Paragraph", "RightArrow", "RightPointer", "Star", "UpArrow", "UpLeftArrow"};
std::vector<std::string>::iterator p = std::find(arrName.begin(), arrName.end(), sName);
if (p != arrName.end())
m_nName = p - arrName.begin();
}
oObj.free();
// 17 - Модель состояния - StateModel
if (oAnnot.dictLookup("StateModel", &oObj)->isString())
{
m_unFlags |= (1 << 17);
TextString* s = new TextString(oObj.getString());
std::string sStateModel = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
m_nStateModel = 1; // Review
if (sStateModel == "Marked")
m_nStateModel = 0;
}
oObj.free();
// 18 - Состояние - State
if (oAnnot.dictLookup("State", &oObj)->isString())
{
m_unFlags |= (1 << 18);
TextString* s = new TextString(oObj.getString());
std::string sState = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
m_nState = 6; // None
if (sState == "Marked")
m_nState = 0;
else if (sState == "Unmarked")
m_nState = 1;
else if (sState == "Accepted")
m_nState = 2;
else if (sState == "Rejected")
m_nState = 3;
else if (sState == "Cancelled")
m_nState = 4;
else if (sState == "Completed")
m_nState = 5;
}
oObj.free();
oAnnot.free();
}
//------------------------------------------------------------------------
// Ink
//------------------------------------------------------------------------
CAnnotInk::CAnnotInk(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
Object oAnnot, oObj, oObj2;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// Путь - InkList
if (oAnnot.dictLookup("InkList", &oObj)->isArray())
{
for (int j = 0; j < oObj.arrayGetLength(); ++j)
{
if (oObj.arrayGet(j, &oObj2)->isArray())
{
std::vector<double> arrLine;
for (int k = 0; k < oObj2.arrayGetLength(); ++k)
{
Object oObj1;
if (oObj2.arrayGet(k, &oObj1)->isNum())
arrLine.push_back(k % 2 == 0 ? oObj1.getNum() - m_dX : m_dHeight - oObj1.getNum());
else
arrLine.push_back(0.0);
oObj1.free();
}
if (!arrLine.empty())
m_arrInkList.push_back(arrLine);
}
}
}
oObj.free();
oAnnot.free();
}
//------------------------------------------------------------------------
// Line
//------------------------------------------------------------------------
CAnnotLine::CAnnotLine(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
Object oAnnot, oObj, oObj2;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// Координаты линии - L
if (oAnnot.dictLookup("L", &oObj)->isArray())
{
m_pL[0] = ArrGetNum(&oObj, 0) - m_dX;
m_pL[1] = m_dHeight - ArrGetNum(&oObj, 1);
m_pL[2] = ArrGetNum(&oObj, 2) - m_dX;
m_pL[3] = m_dHeight - ArrGetNum(&oObj, 3);
}
oObj.free();
// 15 - Стили окончания линии - LE
if (oAnnot.dictLookup("LE", &oObj)->isArray())
{
m_unFlags |= (1 << 15);
m_nLE[0] = 5; m_nLE[1] = 5; // None
for (int i = 0; i < oObj.arrayGetLength() && i < 2; ++i)
{
if (oObj.arrayGet(i, &oObj2)->isName())
m_nLE[i] = getLE(&oObj2);
oObj2.free();
}
}
oObj.free();
// 16 - Цвет окончаний линии - IC
if (oAnnot.dictLookup("IC", &oObj)->isArray())
{
m_unFlags |= (1 << 16);
for (int j = 0; j < oObj.arrayGetLength(); ++j)
{
m_arrIC.push_back(oObj.arrayGet(j, &oObj2)->isNum() ? oObj2.getNum() : 0.0);
oObj2.free();
}
}
oObj.free();
// 17 - Длина линий выноски - LL
if (oAnnot.dictLookup("LL", &oObj)->isNum())
{
m_unFlags |= (1 << 17);
m_dLL = oObj.getNum();
}
oObj.free();
// 18 - Продолжение линий выноски - LLE
if (oAnnot.dictLookup("LLE", &oObj)->isNum())
{
m_unFlags |= (1 << 18);
m_dLLE = oObj.getNum();
}
oObj.free();
// 19 - Местоположение заголовка - Cap
if (oAnnot.dictLookup("Cap", &oObj)->isBool())
m_unFlags |= (1 << 19);
oObj.free();
// 20 - Назначение аннотации - IT
if (oAnnot.dictLookup("IT", &oObj)->isName())
{
m_unFlags |= (1 << 20);
m_nIT = 0; // LineDimension
if (oObj.isName("LineArrow"))
m_nIT = 1;
}
oObj.free();
// 21 - Длина смещения выноски - LLO
if (oAnnot.dictLookup("LLO", &oObj)->isNum())
{
m_unFlags |= (1 << 21);
m_dLLO = oObj.getNum();
}
oObj.free();
// 22 - Расположение заголовка аннотации - CP
if (oAnnot.dictLookup("CP", &oObj)->isName())
{
m_unFlags |= (1 << 22);
m_nCP = 0; // Inline
if (oObj.isName("Top"))
m_nCP = 1;
}
oObj.free();
// 23 - Смещение текста подписи - CO
m_pCO[0] = 0.0; m_pCO[1] = 0.0;
if (oAnnot.dictLookup("CO", &oObj)->isArray())
{
m_unFlags |= (1 << 23);
m_pCO[0] = ArrGetNum(&oObj, 0);
m_pCO[1] = ArrGetNum(&oObj, 1);
}
oObj.free();
oAnnot.free();
}
//------------------------------------------------------------------------
// TextMarkup: Highlight, Underline, Squiggly, StrikeOut
//------------------------------------------------------------------------
CAnnotTextMarkup::CAnnotTextMarkup(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
Object oAnnot, oObj, oObj2;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// Координаты - QuadPoints
if (oAnnot.dictLookup("QuadPoints", &oObj)->isArray())
{
for (int i = 0; i < oObj.arrayGetLength(); ++i)
{
if (oObj.arrayGet(i, &oObj2)->isNum())
m_arrQuadPoints.push_back(i % 2 == 0 ? oObj2.getNum() - m_dX : m_dHeight - oObj2.getNum());
oObj2.free();
}
}
oObj.free();
// Подтип - Subtype
std::string sType;
if (oAnnot.dictLookup("Subtype", &oObj)->isName())
sType = oObj.getName();
oObj.free();
if (sType == "Highlight")
m_nSubtype = 8;
else if (sType == "Underline")
m_nSubtype = 9;
else if (sType == "Squiggly")
m_nSubtype = 10;
else if (sType == "StrikeOut")
m_nSubtype = 11;
oAnnot.free();
}
//------------------------------------------------------------------------
// Square, Circle
//------------------------------------------------------------------------
CAnnotSquareCircle::CAnnotSquareCircle(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
Object oAnnot, oObj, oObj2;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// Подтип - Subtype
std::string sType;
if (oAnnot.dictLookup("Subtype", &oObj)->isName())
sType = oObj.getName();
oObj.free();
if (sType == "Square")
m_nSubtype = 4;
else if (sType == "Circle")
m_nSubtype = 5;
// 15 - Различия Rect и фактического размера - RD
if (oAnnot.dictLookup("RD", &oObj)->isArray())
{
m_unFlags |= (1 << 15);
m_pRD[0] = ArrGetNum(&oObj, 0);
m_pRD[3] = ArrGetNum(&oObj, 1);
m_pRD[2] = ArrGetNum(&oObj, 2);
m_pRD[1] = ArrGetNum(&oObj, 3);
}
oObj.free();
// 16 - Цвет заполнения - IC
if (oAnnot.dictLookup("IC", &oObj)->isArray())
{
m_unFlags |= (1 << 16);
for (int j = 0; j < oObj.arrayGetLength(); ++j)
{
m_arrIC.push_back(oObj.arrayGet(j, &oObj2)->isNum() ? oObj2.getNum() : 0.0);
oObj2.free();
}
}
oObj.free();
oAnnot.free();
}
//------------------------------------------------------------------------
// Polygon, PolyLine
//------------------------------------------------------------------------
CAnnotPolygonLine::CAnnotPolygonLine(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
Object oAnnot, oObj, oObj2;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// Подтип - Subtype
std::string sType;
if (oAnnot.dictLookup("Subtype", &oObj)->isName())
sType = oObj.getName();
oObj.free();
if (sType == "Polygon")
m_nSubtype = 6;
else if (sType == "PolyLine")
m_nSubtype = 7;
// Координаты вершин - Vertices
if (oAnnot.dictLookup("Vertices", &oObj)->isArray())
{
for (int j = 0; j < oObj.arrayGetLength(); ++j)
{
if (oObj.arrayGet(j, &oObj2)->isNum())
m_arrVertices.push_back(j % 2 == 0 ? oObj2.getNum() - m_dX : m_dHeight - oObj2.getNum());
else
m_arrVertices.push_back(0.0);
oObj2.free();
}
}
oObj.free();
// 15 - Стили окончания линии - LE
if (oAnnot.dictLookup("LE", &oObj)->isArray())
{
m_unFlags |= (1 << 15);
m_nLE[0] = 5; m_nLE[1] = 5; // None
for (int i = 0; i < oObj.arrayGetLength() && i < 2; ++i)
{
if (oObj.arrayGet(i, &oObj2)->isName())
m_nLE[i] = getLE(&oObj2);
oObj2.free();
}
}
oObj.free();
// 16 - Цвет заполнения - IC
if (oAnnot.dictLookup("IC", &oObj)->isArray())
{
m_unFlags |= (1 << 16);
for (int j = 0; j < oObj.arrayGetLength(); ++j)
{
m_arrIC.push_back(oObj.arrayGet(j, &oObj2)->isNum() ? oObj2.getNum() : 0.0);
oObj2.free();
}
}
oObj.free();
// 20 - Назначение аннотации - IT
if (oAnnot.dictLookup("IT", &oObj)->isName())
{
m_unFlags |= (1 << 20);
m_nIT = 0; // PolygonCloud
if (oObj.isName("PolyLineDimension"))
m_nIT = 1;
else if (oObj.isName("PolygonDimension"))
m_nIT = 2;
}
oObj.free();
oAnnot.free();
}
//------------------------------------------------------------------------
// FreeText
//------------------------------------------------------------------------
CAnnotFreeText::CAnnotFreeText(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
Object oAnnot, oObj, oObj2;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// Выравнивание текста - Q
m_nQ = 0;
if (oAnnot.dictLookup("Q", &oObj)->isInt())
m_nQ = oObj.getInt();
oObj.free();
m_nRotate = 0;
if (oAnnot.dictLookup("Rotate", &oObj)->isInt())
m_nRotate = oObj.getInt();
oObj.free();
// 15 - Различия Rect и фактического размера - RD
if (oAnnot.dictLookup("RD", &oObj)->isArray())
{
m_unFlags |= (1 << 15);
m_pRD[0] = ArrGetNum(&oObj, 0);
m_pRD[3] = ArrGetNum(&oObj, 1);
m_pRD[2] = ArrGetNum(&oObj, 2);
m_pRD[1] = ArrGetNum(&oObj, 3);
}
oObj.free();
// 16 - Координаты выноски - CL
if (oAnnot.dictLookup("CL", &oObj)->isArray())
{
m_unFlags |= (1 << 16);
for (int j = 0; j < oObj.arrayGetLength(); ++j)
{
if (oObj.arrayGet(j, &oObj2)->isNum())
m_arrCL.push_back(j % 2 == 0 ? oObj2.getNum() - m_dX : m_dHeight - oObj2.getNum());
else
m_arrCL.push_back(0.0);
oObj2.free();
}
}
oObj.free();
// 17 - Строка стиля по умолчанию - DS
m_sDS = DictLookupString(&oAnnot, "DS", 17);
// 18 - Стили окончания линии - LE
if (oAnnot.dictLookup("LE", &oObj)->isName())
{
m_unFlags |= (1 << 18);
m_nLE = getLE(&oObj);
}
oObj.free();
// 20 - Назначение аннотации - IT
if (oAnnot.dictLookup("IT", &oObj)->isName())
{
m_unFlags |= (1 << 20);
m_nIT = 0; // FreeText
if (oObj.isName("FreeTextCallout"))
m_nIT = 1;
else if (oObj.isName("FreeTextTypeWriter"))
m_nIT = 2;
}
oObj.free();
// 21 - Цвет границы - color from DA
if (oAnnot.dictLookup("DA", &oObj)->isString())
{
m_unFlags |= (1 << 21);
int nSpace;
GList *arrColors = new GList();
// parse the default appearance string
GList* daToks = tokenize(oObj.getString());
for (int i = daToks->getLength() - 1; i > 0; --i) {
// handle the g operator
if (!((GString *)daToks->get(i))->cmp("g")) {
arrColors->append(new double(atof(((GString *)daToks->get(i - 1))->getCString())));
break;
// handle the rg operator
} else if (i >= 3 && !((GString *)daToks->get(i))->cmp("rg")) {
arrColors->append(new double(atof(((GString *)daToks->get(i - 3))->getCString())));
arrColors->append(new double(atof(((GString *)daToks->get(i - 2))->getCString())));
arrColors->append(new double(atof(((GString *)daToks->get(i - 1))->getCString())));
break;
} else if (i >= 4 && !((GString *)daToks->get(i))->cmp("k")) {
arrColors->append(new double(atof(((GString *)daToks->get(i - 4))->getCString())));
arrColors->append(new double(atof(((GString *)daToks->get(i - 3))->getCString())));
arrColors->append(new double(atof(((GString *)daToks->get(i - 2))->getCString())));
arrColors->append(new double(atof(((GString *)daToks->get(i - 1))->getCString())));
break;
}
}
deleteGList(daToks, GString);
nSpace = arrColors->getLength();
for (int j = 0; j < nSpace; ++j)
m_arrCFromDA.push_back(*(double*)arrColors->get(j));
deleteGList(arrColors, double);
}
oObj.free();
if (oAnnot.dictLookup("RC", &oObj2)->isNull() && oAnnot.dictLookup("Contents", &oObj)->isString() && oObj.getString()->getLength())
{
m_arrRC = CAnnotMarkup::ReadRC(GetRCFromDS(m_sDS, &oObj, m_arrCFromDA));
if (m_arrRC.empty())
m_unFlags &= ~(1 << 3);
else
m_unFlags |= (1 << 3);
}
oObj.free(); oObj2.free();
oAnnot.free();
}
//------------------------------------------------------------------------
// Caret
//------------------------------------------------------------------------
CAnnotCaret::CAnnotCaret(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
Object oAnnot, oObj, oObj2;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// 15 - Различия Rect и фактического размера - RD
if (oAnnot.dictLookup("RD", &oObj)->isArray() && oObj.arrayGetLength() == 4)
{
m_unFlags |= (1 << 15);
m_pRD[0] = ArrGetNum(&oObj, 0);
m_pRD[3] = ArrGetNum(&oObj, 1);
m_pRD[2] = ArrGetNum(&oObj, 2);
m_pRD[1] = ArrGetNum(&oObj, 3);
}
oObj.free();
// 16 - Связанный символ - Sy
if (oAnnot.dictLookup("Sy", &oObj)->isName())
{
m_unFlags |= (1 << 16);
m_nSy = 0; // None
if (oObj.isName("P"))
m_nSy = 1;
if (oObj.isName("S"))
m_nSy = 2;
}
oObj.free();
oAnnot.free();
}
//------------------------------------------------------------------------
// FileAttachment
//------------------------------------------------------------------------
CAnnotFileAttachment::CAnnotFileAttachment(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
m_pEF = NULL;
Object oAnnot, oObj, oObj2;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// 15 - Иконка - Name
if (oAnnot.dictLookup("Name", &oObj)->isName())
{
m_unFlags |= (1 << 15);
m_sName = oObj.getName();
}
oObj.free();
Object oFS;
if (!oAnnot.dictLookup("FS", &oFS)->isDict())
{
oFS.free(); oAnnot.free();
return;
}
// 16 - Файловая система - FS
if (oFS.dictLookup("FS", &oObj)->isName())
{
m_unFlags |= (1 << 16);
m_sFS = oObj.getName();
}
oObj.free();
// 17 - Спецификация файла - F
m_sF = DictLookupString(&oFS, "F", 17);
// 18 - Спецификация файла - UF
m_sUF = DictLookupString(&oFS, "UF", 18);
// 19 - Спецификация файла - DOS
m_sDOS = DictLookupString(&oFS, "DOS", 19);
// 20 - Спецификация файла - Mac
m_sMac = DictLookupString(&oFS, "Mac", 20);
// 21 - Спецификация файла - Unix
m_sUnix = DictLookupString(&oFS, "Unix", 21);
// 22 - Идентификатор файла - ID
if (oFS.dictLookup("ID", &oObj)->isArray() && oObj.arrayGetLength() == 2)
{
m_unFlags |= (1 << 22);
if (oObj.arrayGet(0, &oObj2)->isString())
{
TextString* s = new TextString(oObj2.getString());
m_sID.first = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj2.free();
if (oObj.arrayGet(1, &oObj2)->isString())
{
TextString* s = new TextString(oObj2.getString());
m_sID.second = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj2.free();
}
oObj.free();
// 23 - Изменчивость файла - V
if (oFS.dictLookup("V", &oObj)->isBool() && oObj.getBool())
m_unFlags |= (1 << 23);
oObj.free();
// 24 - Встроенные файловые потоки - EF
Object oEF;
if (oFS.dictLookup("EF", &oEF)->isDict())
{
m_unFlags |= (1 << 24);
m_pEF = new CEmbeddedFiles();
if (oEF.dictLookup("F", &oObj)->isStream())
m_pEF->m_pF = getEF(&oObj);
oObj.free();
if (oEF.dictLookup("UF", &oObj)->isStream())
m_pEF->m_pUF = getEF(&oObj);
oObj.free();
if (oEF.dictLookup("DOS", &oObj)->isStream())
m_pEF->m_pDOS = getEF(&oObj);
oObj.free();
if (oEF.dictLookup("Mac", &oObj)->isStream())
m_pEF->m_pMac = getEF(&oObj);
oObj.free();
if (oEF.dictLookup("Unix", &oObj)->isStream())
m_pEF->m_pUnix = getEF(&oObj);
oObj.free();
}
oEF.free();
// 25 - Встроенные файловые потоки - RF
if (oFS.dictLookup("RF", &oObj)->isDict())
m_unFlags |= (1 << 25);
oObj.free();
// 26 - Описание файла - Desc
m_sDesc = DictLookupString(&oFS, "Desc", 26);
// 27 - Коллекция - Cl
if (oFS.dictLookup("Cl", &oObj)->isDict())
m_unFlags |= (1 << 27);
oObj.free();
oFS.free(); oAnnot.free();
}
CAnnotFileAttachment::~CAnnotFileAttachment()
{
RELEASEOBJECT(m_pEF);
}
//------------------------------------------------------------------------
// Stamp
//------------------------------------------------------------------------
CAnnotStamp::CAnnotStamp(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
Object oAnnot, oObj;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// Иконка - Name
if (oAnnot.dictLookup("Name", &oObj)->isName())
m_sName = oObj.getName();
oObj.free();
m_dRotate = 0;
if (oAnnot.dictLookup("Rotate", &oObj)->isNum())
m_dRotate = oObj.getNum();
oObj.free();
double m[6] = { 1, 0, 0, 1, 0, 0 }, bbox[4] = { 0, 0, 0, 0 };
Object oAP, oObj2;
if (oAnnot.dictLookup("AP", &oAP)->isDict() && oAP.dictLookup("N", &oObj2)->isStream())
{
Object oObj1;
if (oObj2.streamGetDict()->lookup("BBox", &oObj)->isArray() && oObj.arrayGetLength() == 4)
{
for (int i = 0; i < 4; ++i)
{
oObj.arrayGet(i, &oObj1);
bbox[i] = oObj1.isNum() ? oObj1.getNum() : 0;
oObj1.free();
}
}
oObj.free();
if (oObj2.streamGetDict()->lookup("Matrix", &oObj)->isArray() && oObj.arrayGetLength() == 6)
{
for (int i = 0; i < 6; ++i)
{
oObj.arrayGet(i, &oObj1);
m[i] = oObj1.getNum();
oObj1.free();
}
}
}
else
{
m_dX1 = 0;
m_dY1 = 0;
m_dX2 = 0;
m_dY2 = 0;
m_dX3 = 0;
m_dY3 = 0;
m_dX4 = 0;
m_dY4 = 0;
return;
}
oAP.free(); oObj2.free(); oObj.free();
double formXMin, formYMin, formXMax, formYMax, x, y, sx, sy;
x = bbox[0] * m[0] + bbox[1] * m[2] + m[4];
y = bbox[0] * m[1] + bbox[1] * m[3] + m[5];
formXMin = formXMax = x;
formYMin = formYMax = y;
x = bbox[0] * m[0] + bbox[3] * m[2] + m[4];
y = bbox[0] * m[1] + bbox[3] * m[3] + m[5];
if (x < formXMin)
formXMin = x;
else if (x > formXMax)
formXMax = x;
if (y < formYMin)
formYMin = y;
else if (y > formYMax)
formYMax = y;
x = bbox[2] * m[0] + bbox[1] * m[2] + m[4];
y = bbox[2] * m[1] + bbox[1] * m[3] + m[5];
if (x < formXMin)
formXMin = x;
else if (x > formXMax)
formXMax = x;
if (y < formYMin)
formYMin = y;
else if (y > formYMax)
formYMax = y;
x = bbox[2] * m[0] + bbox[3] * m[2] + m[4];
y = bbox[2] * m[1] + bbox[3] * m[3] + m[5];
if (x < formXMin)
formXMin = x;
else if (x > formXMax)
formXMax = x;
if (y < formYMin)
formYMin = y;
else if (y > formYMax)
formYMax = y;
if (formXMin == formXMax)
sx = 1;
else
sx = (m_pRect[2] - m_pRect[0]) / (formXMax - formXMin);
if (formYMin == formYMax)
sy = 1;
else
sy = (m_pRect[3] - m_pRect[1]) / (formYMax - formYMin);
double tx = -formXMin * sx + m_pRect[0];
double ty = -formYMin * sy - m_pRect[3] + m_dHeight;
m[0] *= sx;
m[1] *= sy;
m[2] *= sx;
m[3] *= sy;
m[4] = m[4] * sx + tx;
m[5] = m[5] * sy + ty;
m_dX1 = bbox[0] * m[0] + bbox[1] * m[2] + m[4];
m_dY1 = m_dHeight - (bbox[0] * m[1] + bbox[1] * m[3] + m[5]);
m_dX2 = bbox[0] * m[0] + bbox[3] * m[2] + m[4];
m_dY2 = m_dHeight - (bbox[0] * m[1] + bbox[3] * m[3] + m[5]);
m_dX3 = bbox[2] * m[0] + bbox[3] * m[2] + m[4];
m_dY3 = m_dHeight - (bbox[2] * m[1] + bbox[3] * m[3] + m[5]);
m_dX4 = bbox[2] * m[0] + bbox[1] * m[2] + m[4];
m_dY4 = m_dHeight - (bbox[2] * m[1] + bbox[1] * m[3] + m[5]);
oAnnot.free();
}
//------------------------------------------------------------------------
// Redact
//------------------------------------------------------------------------
CAnnotRedact::CAnnotRedact(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnotMarkup(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
Object oAnnot, oObj, oObj2;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// 15 - Координаты - QuadPoints
if (oAnnot.dictLookup("QuadPoints", &oObj)->isArray())
{
m_unFlags |= (1 << 15);
for (int i = 0; i < oObj.arrayGetLength(); ++i)
{
if (oObj.arrayGet(i, &oObj2)->isNum())
m_arrQuadPoints.push_back(i % 2 == 0 ? oObj2.getNum() - m_dX : m_dHeight - oObj2.getNum());
oObj2.free();
}
}
oObj.free();
// 16 - Цвет заполнения - IC
if (oAnnot.dictLookup("IC", &oObj)->isArray())
{
m_unFlags |= (1 << 16);
for (int j = 0; j < oObj.arrayGetLength(); ++j)
{
m_arrIC.push_back(oObj.arrayGet(j, &oObj2)->isNum() ? oObj2.getNum() : 0.0);
oObj2.free();
}
}
oObj.free();
// RO во внешних видах
// 17 - Текст наложения - OverlayText
m_sOverlayText = DictLookupString(&oAnnot, "OverlayText", 17);
// 18 - Повторять текст - Repeat
if (oAnnot.dictLookup("Repeat", &oObj)->isBool() && oObj.getBool())
m_unFlags |= (1 << 18);
// 19 - Выравнивание текста - Q
m_nQ = 0;
if (oAnnot.dictLookup("Q", &oObj)->isInt())
{
m_unFlags |= (1 << 19);
m_nQ = oObj.getInt();
}
oObj.free();
// Замена C: 3 - Цвет - C
if (oAnnot.dictLookup("OC", &oObj)->isArray())
{
m_unAFlags |= (1 << 3);
int nBCLength = oObj.arrayGetLength();
m_arrC.clear();
for (int j = 0; j < nBCLength; ++j)
{
m_arrC.push_back(oObj.arrayGet(j, &oObj2)->isNum() ? oObj2.getNum() : 0.0);
oObj2.free();
}
}
oObj.free();
oAnnot.free();
}
void CAnnotRedact::SetFont(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, Object* oAnnotRef)
{
Object oAnnot, oObj;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// 20 - Шрифт, размер, цвет текста замены - DA
if (oAnnot.dictLookup("DA", &oObj)->isString())
{
m_unFlags |= (1 << 20);
// parse the default appearance string
GList* daToks = tokenize(oObj.getString());
for (int i = daToks->getLength() - 1; i > 0; --i)
{
// handle the g operator
if (!((GString *)daToks->get(i))->cmp("G") && m_arrCFromDA.empty())
{
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 1))->getCString()));
}
// handle the rg operator
else if (i >= 3 && !((GString *)daToks->get(i))->cmp("RG") && m_arrCFromDA.empty())
{
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 3))->getCString()));
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 2))->getCString()));
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 1))->getCString()));
}
// handle the k operator
else if (i >= 4 && !((GString *)daToks->get(i))->cmp("K") && m_arrCFromDA.empty())
{
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 4))->getCString()));
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 3))->getCString()));
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 2))->getCString()));
m_arrCFromDA.push_back(atof(((GString *)daToks->get(i - 1))->getCString()));
}
else if (i >= 2 && !((GString *)daToks->get(i))->cmp("Tf"))
{
m_dFontSize = atof(((GString *)daToks->get(i - 1))->getCString());
m_unFontStyle = 0;
}
}
deleteGList(daToks, GString);
}
oObj.free();
Object oAP, oN;
if (!oAnnot.dictLookup("RO", &oN)->isStream())
{
oN.free();
if (!oAnnot.dictLookup("AP", &oAP)->isDict() || !oAP.dictLookup("D", &oN)->isStream())
{
oAP.free(); oN.free(); oAnnot.free();
return;
}
}
oAP.free();
Object oFonts;
if (!CAnnotFonts::FindFonts(&oN, 0, &oFonts))
{
oN.free(); oFonts.free(); oAnnot.free();
return;
}
oN.free();
for (int i = 0, nFonts = oFonts.dictGetLength(); i < nFonts; ++i)
{
Object oFontRef;
if (!oFonts.dictGetValNF(i, &oFontRef)->isRef())
{
oFontRef.free();
continue;
}
std::string sFontName, sActualFontName;
bool bBold = false, bItalic = false;
std::wstring sFontPath = CAnnotFonts::GetFontData(pdfDoc, pFontManager, pFontList, &oFontRef, m_sFontName, m_sActualFontName, bBold, bItalic);
oFontRef.free();
m_unFontStyle = 0;
if (bBold)
m_unFontStyle |= (1 << 0);
if (bItalic)
m_unFontStyle |= (1 << 1);
}
oFonts.free(); oAnnot.free();
}
//------------------------------------------------------------------------
// Annots
//------------------------------------------------------------------------
CAnnots::CAnnots(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList, int nStartPage, int nStartRefID)
{
Object oObj1, oObj2;
XRef* xref = pdfDoc->getXRef();
AcroForm* pAcroForms = pdfDoc->getCatalog()->getForm();
// Порядок вычислений - CO
Object* oAcroForm = pAcroForms->getAcroFormObj();
if (oAcroForm->dictLookup("CO", &oObj1)->isArray())
{
for (int j = 0; j < oObj1.arrayGetLength(); ++j)
{
if (oObj1.arrayGetNF(j, &oObj2)->isRef())
m_arrCO.push_back(oObj2.getRefNum() + nStartRefID);
oObj2.free();
}
}
oObj1.free();
// Fields
for (int i = 0, nNum = pAcroForms->getNumFields(); i < nNum; ++i)
{
AcroFormField* pField = pAcroForms->getField(i);
Object oFieldRef, oField;
if (!pField || !pField->getFieldRef(&oFieldRef)->isRef() || !oFieldRef.fetch(xref, &oField)->isDict())
{
oField.free(); oFieldRef.free();
continue;
}
if (pField->getPageNum() < 1)
{
oField.free(); oFieldRef.free();
std::vector<int>::iterator it = std::find(m_arrCO.begin(), m_arrCO.end(), oFieldRef.getRefNum() + nStartRefID);
if (it != m_arrCO.end())
m_arrCO.erase(it);
continue;
}
// Родители
Object oParentRefObj;
if (oField.dictLookupNF("Parent", &oParentRefObj)->isRef())
getParents(pdfDoc, &oParentRefObj, nStartRefID);
oParentRefObj.free();
oField.free(); oFieldRef.free();
CAnnotWidget* pAnnot = NULL;
AcroFormFieldType oType = pField->getAcroFormFieldType();
switch (oType)
{
case acroFormFieldPushbutton:
case acroFormFieldRadioButton:
case acroFormFieldCheckbox:
{
pAnnot = new CAnnotWidgetBtn(pdfDoc, pField, nStartRefID);
break;
}
case acroFormFieldFileSelect:
case acroFormFieldMultilineText:
case acroFormFieldText:
case acroFormFieldBarcode:
{
pAnnot = new CAnnotWidgetTx(pdfDoc, pField, nStartRefID);
break;
}
case acroFormFieldComboBox:
case acroFormFieldListBox:
{
pAnnot = new CAnnotWidgetCh(pdfDoc, pField, nStartRefID);
break;
}
case acroFormFieldSignature:
{
pAnnot = new CAnnotWidgetSig(pdfDoc, pField, nStartRefID);
break;
}
default:
break;
}
if (pAnnot)
{
pAnnot->SetFont(pdfDoc, pField, pFontManager, pFontList);
if (pField->getAcroFormFieldType() == acroFormFieldPushbutton)
pAnnot->SetButtonFont(pdfDoc, pField, pFontManager, pFontList);
pAnnot->SetPage(nStartPage + pField->getPageNum());
unsigned int unRefNumParent = pAnnot->GetRefNumParent();
if (unRefNumParent)
{
std::vector<CAnnotParent*>::iterator it = std::find_if(m_arrParents.begin(), m_arrParents.end(), [unRefNumParent](CAnnotParent* pP) { return pP->unRefNum == unRefNumParent; });
if (it != m_arrParents.end() && !((*it)->sFullName.empty()))
{
const std::string& sFullNameChild = pAnnot->GetFullName();
if (sFullNameChild.empty())
pAnnot->SetFullName((*it)->sFullName);
else
pAnnot->SetFullName((*it)->sFullName + "." + sFullNameChild);
}
}
m_arrAnnots.push_back(pAnnot);
}
}
}
CAnnots::~CAnnots()
{
for (int i = 0; i < m_arrParents.size(); ++i)
RELEASEOBJECT(m_arrParents[i]);
for (int i = 0; i < m_arrAnnots.size(); ++i)
RELEASEOBJECT(m_arrAnnots[i]);
}
void CAnnots::getParents(PDFDoc* pdfDoc, Object* oFieldRef, int nStartRefID)
{
if (!oFieldRef || !pdfDoc || !oFieldRef->isRef() ||
std::find_if(m_arrParents.begin(), m_arrParents.end(), [oFieldRef, nStartRefID] (CAnnotParent* pAP) { return oFieldRef->getRefNum() + nStartRefID == pAP->unRefNum; }) != m_arrParents.end())
return;
Object oField;
CAnnotParent* pAnnotParent = new CAnnotParent();
if (!pAnnotParent || !oFieldRef->fetch(pdfDoc->getXRef(), &oField)->isDict())
{
oField.free();
RELEASEOBJECT(pAnnotParent);
return;
}
pAnnotParent->unRefNum = oFieldRef->getRefNum() + nStartRefID;
Object oObj;
if (oField.dictLookup("T", &oObj)->isString())
{
TextString* s = new TextString(oObj.getString());
std::string sStr = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
pAnnotParent->unFlags |= (1 << 0);
pAnnotParent->sT = sStr;
pAnnotParent->sFullName = sStr;
delete s;
}
oObj.free();
if (oField.dictLookup("V", &oObj))
{
pAnnotParent->sV = getValue(&oObj, false);
if (!pAnnotParent->sV.empty())
pAnnotParent->unFlags |= (1 << 1);
if (oObj.isArray())
{
pAnnotParent->unFlags |= (1 << 5);
int nVLength = oObj.arrayGetLength();
for (int j = 0; j < nVLength; ++j)
{
Object oObj2;
if (oObj.arrayGet(j, &oObj2)->isString())
{
TextString* s = new TextString(oObj2.getString());
pAnnotParent->arrV.push_back(NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength()));
delete s;
}
oObj2.free();
}
}
}
oObj.free();
if (oField.dictLookup("DV", &oObj))
{
pAnnotParent->sDV = getValue(&oObj);
if (!pAnnotParent->sDV.empty())
pAnnotParent->unFlags |= (1 << 2);
}
oObj.free();
Object oI;
if (oField.dictLookup("I", &oI)->isArray())
{
int nILength = oI.arrayGetLength();
for (int j = 0; j < nILength; ++j)
{
if (oI.arrayGet(j, &oObj)->isInt())
pAnnotParent->arrI.push_back(oObj.getInt());
oObj.free();
}
if (!pAnnotParent->arrI.empty())
pAnnotParent->unFlags |= (1 << 3);
}
oI.free();
Object oOpt;
// 6 - Opt
if (oField.dictLookup("Opt", &oOpt)->isArray())
{
int nOptLength = oOpt.arrayGetLength();
for (int j = 0; j < nOptLength; ++j)
{
Object oOptJ;
if (!oOpt.arrayGet(j, &oOptJ) || !(oOptJ.isString() || oOptJ.isArray()))
{
oOptJ.free();
continue;
}
std::string sOpt1, sOpt2;
if (oOptJ.isArray() && oOptJ.arrayGetLength() > 1)
{
Object oOptJ2;
if (oOptJ.arrayGet(0, &oOptJ2)->isString())
{
TextString* s = new TextString(oOptJ2.getString());
sOpt1 = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oOptJ2.free();
if (oOptJ.arrayGet(1, &oOptJ2)->isString())
{
TextString* s = new TextString(oOptJ2.getString());
sOpt2 = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oOptJ2.free();
}
else if (oOptJ.isString())
{
TextString* s = new TextString(oOptJ.getString());
sOpt2 = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
pAnnotParent->arrOpt.push_back(std::make_pair(sOpt1, sOpt2));
oOptJ.free();
}
if (!pAnnotParent->arrOpt.empty())
pAnnotParent->unFlags |= (1 << 6);
}
oOpt.free();
// 7 - Флаг - Ff
if (oField.dictLookup("Ff", &oObj)->isInt())
{
pAnnotParent->unFieldFlag = oObj.getInt();
pAnnotParent->unFlags |= (1 << 7);
}
oObj.free();
// 8 - Actions - A/AA
Object oAction;
if (oField.dictLookup("A", &oAction)->isDict())
{
std::string sAA = "A";
CAction* pA = getAction(pdfDoc, &oAction);
if (pA)
{
pA->sType = sAA;
pAnnotParent->arrAction.push_back(pA);
pAnnotParent->unFlags |= (1 << 8);
}
}
oAction.free();
Object oAA;
if (oField.dictLookup("AA", &oAA)->isDict())
{
for (int j = 0; j < oAA.dictGetLength(); ++j)
{
if (oAA.dictGetVal(j, &oAction)->isDict())
{
std::string sAA(oAA.dictGetKey(j));
CAction* pA = getAction(pdfDoc, &oAction);
if (pA)
{
pA->sType = sAA;
pAnnotParent->arrAction.push_back(pA);
pAnnotParent->unFlags |= (1 << 8);
}
}
oAction.free();
}
}
oAA.free();
// 9 - MaxLen
if (oField.dictLookup("MaxLen", &oObj)->isInt())
{
pAnnotParent->unMaxLen = oObj.getInt();
pAnnotParent->unFlags |= (1 << 9);
}
oObj.free();
// 10 - TU
if (oField.dictLookup("TU", &oObj)->isString())
{
TextString* s = new TextString(oObj.getString());
std::string sStr = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
pAnnotParent->unFlags |= (1 << 10);
pAnnotParent->sTU = sStr;
delete s;
}
oObj.free();
// 11 - MEOptions
if (oField.dictLookup("MEOptions", &oObj)->isInt())
{
pAnnotParent->unFlags |= (1 << 11);
pAnnotParent->unMEOptions = oObj.getInt();
}
oObj.free();
m_arrParents.push_back(pAnnotParent);
Object oParentRefObj;
if (oField.dictLookupNF("Parent", &oParentRefObj)->isRef())
{
pAnnotParent->unFlags |= (1 << 4);
pAnnotParent->unRefNumParent = oParentRefObj.getRefNum() + nStartRefID;
getParents(pdfDoc, &oParentRefObj, nStartRefID);
unsigned int unRefNumParent = pAnnotParent->unRefNumParent;
std::vector<CAnnotParent*>::iterator it = std::find_if(m_arrParents.begin(), m_arrParents.end(), [unRefNumParent](CAnnotParent* pP) { return pP->unRefNum == unRefNumParent; });
if (it != m_arrParents.end() && !((*it)->sFullName.empty()))
{
if (pAnnotParent->sFullName.empty())
pAnnotParent->sFullName = (*it)->sFullName;
else
pAnnotParent->sFullName = (*it)->sFullName + "." + pAnnotParent->sFullName;
}
}
oParentRefObj.free();
oField.free();
}
bool CAnnots::ChangeFullNameAnnot(int nAnnot, const std::string& sPrefixForm)
{
if (nAnnot < 0 || nAnnot > m_arrAnnots.size())
return false;
CAnnotWidget* pWidget = m_arrAnnots[nAnnot];
if (pWidget->m_bChangeFullName)
return true;
unsigned int unRefNumParent = pWidget->GetRefNumParent();
if (unRefNumParent)
{
std::vector<CAnnotParent*>::iterator it = std::find_if(m_arrParents.begin(), m_arrParents.end(), [unRefNumParent](CAnnotParent* pP) { return pP->unRefNum == unRefNumParent; });
if (it != m_arrParents.end() && ChangeFullNameParent(std::distance(m_arrParents.begin(), it), sPrefixForm))
{
const std::string& sFullNameChild = pWidget->GetFullName();
if (sFullNameChild.empty())
pWidget->SetFullName((*it)->sFullName);
else
pWidget->SetFullName((*it)->sFullName + "." + sFullNameChild);
pWidget->m_bChangeFullName = true;
return true;
}
}
return pWidget->ChangeFullName(sPrefixForm);
}
bool CAnnots::ChangeFullNameParent(int nParent, const std::string& sPrefixForm)
{
if (nParent < 0 || nParent > m_arrParents.size())
return false;
CAnnotParent* pParent = m_arrParents[nParent];
if (pParent->bChangeFullName)
return true;
if (pParent->unFlags & (1 << 4))
{
unsigned int unRefNumParent = pParent->unRefNumParent;
std::vector<CAnnotParent*>::iterator it = std::find_if(m_arrParents.begin(), m_arrParents.end(), [unRefNumParent](CAnnotParent* pP) { return pP->unRefNum == unRefNumParent; });
if (it != m_arrParents.end() && ChangeFullNameParent(std::distance(m_arrParents.begin(), it), sPrefixForm))
{
if (pParent->sT.empty())
pParent->sFullName = (*it)->sFullName;
else
pParent->sFullName = (*it)->sFullName + "." + sPrefixForm;
pParent->bChangeFullName = true;
return true;
}
}
else if (pParent->unFlags & (1 << 0))
{
pParent->sT += sPrefixForm;
pParent->sFullName += sPrefixForm;
pParent->bChangeFullName = true;
return true;
}
return false;
}
void CAnnots::CAnnotParent::ClearActions()
{
unFlags &= ~(1 << 8);
for (int i = 0; i < arrAction.size(); ++i)
RELEASEOBJECT(arrAction[i]);
arrAction.clear();
}
//------------------------------------------------------------------------
// Markup
//------------------------------------------------------------------------
CAnnotMarkup::CAnnotMarkup(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnot(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
{
m_unFlags = 0;
Object oAnnot, oObj;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// 0 - Всплывающая аннотация - Popup
if (oAnnot.dictLookupNF("Popup", &oObj)->isRef())
{
m_unFlags |= (1 << 0);
m_unRefNumPopup = oObj.getRefNum() + nStartRefID;
}
// 1 - Текстовая метка пользователя - T
m_sT = DictLookupString(&oAnnot, "T", 1);
// 2 - Значение непрозрачности - CA
if (oAnnot.dictLookup("CA", &oObj)->isNum())
{
m_unFlags |= (1 << 2);
m_dCA = oObj.getNum();
}
oObj.free();
// 3 - Форматированный текст - RC
std::string sRC = DictLookupString(&oAnnot, "RC", 3);
// std::cout << sRC << std::endl;
// if (oAnnot.dictLookup("RC", &oObj)->isStream())
// TODO streamGetBlock
m_arrRC = CAnnotMarkup::ReadRC(sRC);
if (m_arrRC.empty())
m_unFlags &= ~(1 << 3);
else
m_unFlags |= (1 << 3);
// 4 - Дата создания - CreationDate
m_sCreationDate = DictLookupString(&oAnnot, "CreationDate", 4);
// 5 - Ссылка на аннотацию ответ - IRT
if (oAnnot.dictLookupNF("IRT", &oObj)->isRef())
{
m_unFlags |= (1 << 5);
m_unAFlags &= ~(1 << 6); // IRT аннотации не отображаются
m_unRefNumIRT = oObj.getRefNum() + nStartRefID;
}
oObj.free();
// 6 - Тип аннотации ответа - RT
if (oAnnot.dictLookup("RT", &oObj)->isName())
{
m_unFlags |= (1 << 6);
m_nRT = 1; // Group
if (oObj.isName("R"))
m_nRT = 0;
}
oObj.free();
// 7 - Краткое описание - Subj
m_sSubj = DictLookupString(&oAnnot, "Subj", 7);
oAnnot.free();
}
CAnnotMarkup::~CAnnotMarkup()
{
for (int i = 0; i < m_arrRC.size(); ++i)
RELEASEOBJECT(m_arrRC[i]);
}
void ReadFontData(const std::string& sData, CAnnotMarkup::CFontData* pFont)
{
size_t nSemicolon = 0;
size_t nColon = sData.find(':');
while (nColon != std::string::npos && nColon > nSemicolon)
{
std::string sProperty = sData.substr(nSemicolon, nColon - nSemicolon);
nSemicolon = sData.find(';', nSemicolon);
nColon++;
std::string sValue = sData.substr(nColon, nSemicolon - nColon);
nColon = sData.find(':', nSemicolon);
nSemicolon++;
if (sProperty == "font-size")
pFont->dFontSise = std::stod(sValue);
else if (sProperty == "text-align")
{
// 0 start / left
if (sValue == "center" || sValue == "middle")
pFont->nAlign = 1;
else if (sValue == "right" || sValue == "end")
pFont->nAlign = 2;
else if (sValue == "justify")
pFont->nAlign = 3;
}
else if (sProperty == "color")
{
if (sValue[0] == '#')
{
sValue = sValue.substr(1);
BYTE nColor1 = 0, nColor2 = 0, nColor3 = 0;
if (sValue.length() == 6)
sscanf(sValue.c_str(), "%2hhx%2hhx%2hhx", &nColor1, &nColor2, &nColor3);
else if (sValue.length() == 3)
{
sscanf(sValue.c_str(), "%1hhx%1hhx%1hhx", &nColor1, &nColor2, &nColor3);
nColor1 *= 17;
nColor2 *= 17;
nColor3 *= 17;
}
pFont->dColor[0] = (double)nColor1 / 255.0;
pFont->dColor[1] = (double)nColor2 / 255.0;
pFont->dColor[2] = (double)nColor3 / 255.0;
}
}
else if (sProperty == "font-weight")
{
// 0 normal / 300 / 400 / 500
if (sValue == "normal" || sValue == "300" || sValue == "400" || sValue == "500")
pFont->unFontFlags &= ~(1 << 0);
else if (sValue == "bold" || sValue == "bolder" || sValue == "600" || sValue == "700" || sValue == "800" || sValue == "900")
pFont->unFontFlags |= (1 << 0);
}
else if (sProperty == "font-style")
{
// 0 normal
if (sValue == "normal")
pFont->unFontFlags &= ~(1 << 1);
else if (sValue == "italic" || sValue.find("oblique") != std::string::npos)
pFont->unFontFlags |= (1 << 1);
}
else if (sProperty == "font-family")
pFont->sFontFamily = sValue[0] == '\'' ? sValue.substr(1, sValue.length() - 2) : sValue;
else if (sProperty == "text-decoration")
{
if (sValue.find("line-through") != std::string::npos)
pFont->unFontFlags |= (1 << 3);
if (sValue.find("word") != std::string::npos || sValue.find("underline") != std::string::npos)
pFont->unFontFlags |= (1 << 4);
if (sValue.find("none") != std::string::npos)
{
pFont->unFontFlags &= ~(1 << 3);
pFont->unFontFlags &= ~(1 << 4);
}
}
else if (sProperty == "vertical-align")
{
pFont->unFontFlags |= (1 << 5);
pFont->dVAlign = std::stod(sValue);
if (pFont->dVAlign == 0 && sValue[0] == '-')
pFont->dVAlign = -0.01;
}
// font-stretch
}
}
std::vector<CAnnotMarkup::CFontData*> CAnnotMarkup::ReadRC(const std::string& sRC)
{
std::vector<CAnnotMarkup::CFontData*> arrRC;
XmlUtils::CXmlLiteReader oLightReader;
if (sRC.empty() || !oLightReader.FromStringA(sRC) || !oLightReader.ReadNextNode() || oLightReader.GetNameA() != "body")
return arrRC;
CAnnotMarkup::CFontData oFontBase;
while (oLightReader.MoveToNextAttribute())
{
if (oLightReader.GetNameA() == "style")
{
ReadFontData(oLightReader.GetTextA(), &oFontBase);
break;
}
}
oLightReader.MoveToElement();
int nDepthP = oLightReader.GetDepth();
while (oLightReader.ReadNextSiblingNode2(nDepthP))
{
if (oLightReader.GetNameA() != "p")
continue;
bool bRTL = false;
while (oLightReader.MoveToNextAttribute())
{
if (oLightReader.GetNameA() == "dir" && oLightReader.GetTextA() == "rtl")
{
bRTL = true;
break;
}
}
oLightReader.MoveToElement();
int nDepthSpan = oLightReader.GetDepth();
if (oLightReader.IsEmptyNode() || !oLightReader.ReadNextSiblingNode2(nDepthSpan))
continue;
do
{
std::string sName = oLightReader.GetNameA();
if (sName == "span")
{
CAnnotMarkup::CFontData* pFont = new CAnnotMarkup::CFontData(oFontBase);
while (oLightReader.MoveToNextAttribute())
{
if (oLightReader.GetNameA() == "style")
{
ReadFontData(oLightReader.GetTextA(), pFont);
break;
}
}
oLightReader.MoveToElement();
if (bRTL)
pFont->unFontFlags |= (1 << 7);
pFont->sText = oLightReader.GetText2A();
arrRC.push_back(pFont);
}
else if (sName == "#text")
{
CAnnotMarkup::CFontData* pFont = new CAnnotMarkup::CFontData(oFontBase);
if (bRTL)
pFont->unFontFlags |= (1 << 7);
pFont->sText = oLightReader.GetTextA();
arrRC.push_back(pFont);
}
} while (oLightReader.ReadNextSiblingNode2(nDepthSpan));
}
return arrRC;
}
void CAnnotMarkup::SetFont(PDFDoc* pdfDoc, Object* oAnnotRef, NSFonts::IFontManager* pFontManager, CPdfFontList *pFontList)
{
CAnnotFonts::GetFreeTextFont(pdfDoc, pFontManager, pFontList, oAnnotRef, m_arrRC);
}
//------------------------------------------------------------------------
// Annot
//------------------------------------------------------------------------
CAnnot::CAnnot(PDFDoc* pdfDoc, AcroFormField* pField, int nStartRefID)
{
m_pBorder = NULL;
m_unAnnotFlag = 0;
m_unAFlags = 0;
m_unFlags = 0;
Object oObj;
pField->getFieldRef(&oObj);
m_unRefNum = oObj.getRefNum() + nStartRefID;
oObj.free();
// Флаг аннотации - F
if (pField->fieldLookup("F", &oObj)->isInt())
m_unAnnotFlag = oObj.getInt();
oObj.free();
// Номер страницы - P
m_unPage = pField->getPageNum();
// Координаты - Rect
pField->getBBox(&m_pRect[0], &m_pRect[1], &m_pRect[2], &m_pRect[3]);
PDFRectangle* pCropBox = pdfDoc->getCatalog()->getPage(m_unPage)->getCropBox();
m_dHeight = pCropBox->y2;
m_dX = pCropBox->x1;
double dTemp = m_pRect[1];
m_pRect[0] = m_pRect[0] - m_dX;
m_pRect[1] = m_dHeight - m_pRect[3];
m_pRect[2] = m_pRect[2] - m_dX;
m_pRect[3] = m_dHeight - dTemp;
// 0 - Уникальное имя - NM
if (pField->fieldLookup("NM", &oObj)->isString())
{
m_unAFlags |= (1 << 0);
TextString* s = new TextString(oObj.getString());
m_sNM = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
// 1 - Альтернативный текст - Contents
if (pField->fieldLookup("Contents", &oObj)->isString())
{
m_unAFlags |= (1 << 1);
TextString* s = new TextString(oObj.getString());
m_sContents = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
// 2 - Эффекты границы - BE
if (pField->fieldLookup("BE", &oObj)->isDict())
{
Object oBorderBE;
m_unAFlags |= (1 << 2);
m_pBE.first = 0;
if (oObj.dictLookup("S", &oBorderBE)->isName("C"))
m_pBE.first = 1;
oBorderBE.free();
m_pBE.second = 0;
if (oObj.dictLookup("I", &oBorderBE)->isNum())
m_pBE.second = oBorderBE.getNum();
oBorderBE.free();
}
oObj.free();
// 3 - Специальный цвет для аннотации - C
if (pField->fieldLookup("C", &oObj)->isArray())
{
m_unAFlags |= (1 << 3);
int nCLength = oObj.arrayGetLength();
for (int j = 0; j < nCLength; ++j)
{
Object oCj;
m_arrC.push_back(oObj.arrayGet(j, &oCj)->isNum() ? oCj.getNum() : 0.0);
oCj.free();
}
}
oObj.free();
// 4 - Границы и Dash Pattern - Border/BS
m_pBorder = NULL;
if (pField->fieldLookup("BS", &oObj)->isDict())
m_pBorder = getBorder(&oObj, true);
else
{
oObj.free();
if (pField->fieldLookup("Border", &oObj)->isArray() && oObj.arrayGetLength() > 2)
m_pBorder = getBorder(&oObj, false);
}
oObj.free();
if (m_pBorder && m_pBorder->nType != 5)
m_unAFlags |= (1 << 4);
// 5 - Дата последнего изменения - M
if (pField->fieldLookup("M", &oObj)->isString())
{
m_unAFlags |= (1 << 5);
TextString* s = new TextString(oObj.getString());
m_sM = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
// 6 - Наличие/Отсутствие внешнего вида
if (std::abs(m_pRect[2] - m_pRect[0]) * std::abs(m_pRect[3] - m_pRect[1]) < 1073741824.0 / 3.0 && pField->fieldLookup("AP", &oObj)->isDict() && oObj.dictGetLength())
m_unAFlags |= (1 << 6);
oObj.free();
// 7 - User ID
if (pField->fieldLookup("OUserID", &oObj)->isString())
{
m_unAFlags |= (1 << 7);
TextString* s = new TextString(oObj.getString());
m_sOUserID = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
// 9 - OO метаданные форм - OMetadata
if (pField->fieldLookup("OMetadata", &oObj)->isString())
{
m_unAFlags |= (1 << 9);
TextString* s = new TextString(oObj.getString());
m_sOMetadata = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
}
CAnnot::CAnnot(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID)
{
m_pBorder = NULL;
m_unAnnotFlag = 0;
m_unAFlags = 0;
m_unFlags = 0;
Object oAnnot, oObj, oObj2;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// Номер объекта аннотации
m_unRefNum = oAnnotRef->getRefNum() + nStartRefID;
// Флаг аннотации - F
if (oAnnot.dictLookup("F", &oObj)->isInt())
m_unAnnotFlag = oObj.getInt();
oObj.free();
// Номер страницы - P
m_unPage = nPageIndex;
PDFRectangle* pCropBox = pdfDoc->getCatalog()->getPage(m_unPage)->getCropBox();
m_dHeight = pCropBox->y2;
m_dX = pCropBox->x1;
// Координаты - Rect
m_pRect[0] = 0.0, m_pRect[1] = 0.0, m_pRect[2] = 0.0, m_pRect[3] = 0.0;
if (oAnnot.dictLookup("Rect", &oObj)->isArray() && oObj.arrayGetLength() == 4)
{
m_pRect[0] = ArrGetNum(&oObj, 0) - m_dX;
m_pRect[1] = m_dHeight - ArrGetNum(&oObj, 3);
m_pRect[2] = ArrGetNum(&oObj, 2) - m_dX;
m_pRect[3] = m_dHeight - ArrGetNum(&oObj, 1);
}
oObj.free();
// 0 - Уникальное имя - NM
if (oAnnot.dictLookup("NM", &oObj)->isString())
{
m_unAFlags |= (1 << 0);
TextString* s = new TextString(oObj.getString());
m_sNM = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
// 1 - Альтернативный текст - Contents
if (oAnnot.dictLookup("Contents", &oObj)->isString())
{
m_unAFlags |= (1 << 1);
TextString* s = new TextString(oObj.getString());
m_sContents = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
// 2 - Эффекты границы - BE
if (oAnnot.dictLookup("BE", &oObj)->isDict())
{
Object oBorderBE;
m_unAFlags |= (1 << 2);
m_pBE.first = 0;
if (oObj.dictLookup("S", &oBorderBE)->isName("C"))
m_pBE.first = 1;
oBorderBE.free();
m_pBE.second = 0;
if (oObj.dictLookup("I", &oBorderBE)->isNum())
m_pBE.second = oBorderBE.getNum();
oBorderBE.free();
}
oObj.free();
// 3 - Цвет - C
if (oAnnot.dictLookup("C", &oObj)->isArray())
{
m_unAFlags |= (1 << 3);
int nBCLength = oObj.arrayGetLength();
for (int j = 0; j < nBCLength; ++j)
{
m_arrC.push_back(oObj.arrayGet(j, &oObj2)->isNum() ? oObj2.getNum() : 0.0);
oObj2.free();
}
}
oObj.free();
// 4 - Границы и Dash Pattern - Border/BS
m_pBorder = NULL;
if (oAnnot.dictLookup("BS", &oObj)->isDict())
m_pBorder = getBorder(&oObj, true);
else
{
oObj.free();
if (oAnnot.dictLookup("Border", &oObj)->isArray() && oObj.arrayGetLength() > 2)
m_pBorder = getBorder(&oObj, false);
}
oObj.free();
if (m_pBorder && m_pBorder->nType != 5)
m_unAFlags |= (1 << 4);
// 5 - Дата последнего изменения - M
if (oAnnot.dictLookup("M", &oObj)->isString())
{
m_unAFlags |= (1 << 5);
TextString* s = new TextString(oObj.getString());
m_sM = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
// 6 - Наличие/Отсутствие внешнего вида
if (std::abs(m_pRect[2] - m_pRect[0]) * std::abs(m_pRect[3] - m_pRect[1]) < 1073741824.0 / 3.0 && oAnnot.dictLookup("AP", &oObj)->isDict() && oObj.dictGetLength())
m_unAFlags |= (1 << 6);
oObj.free();
// 7 - User ID
if (oAnnot.dictLookup("OUserID", &oObj)->isString())
{
m_unAFlags |= (1 << 7);
TextString* s = new TextString(oObj.getString());
m_sOUserID = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
// 9 - OO метаданные форм - OMetadata
if (oAnnot.dictLookup("OMetadata", &oObj)->isString())
{
m_unAFlags |= (1 << 9);
TextString* s = new TextString(oObj.getString());
m_sOMetadata = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
oAnnot.free();
}
CAnnot::~CAnnot()
{
RELEASEOBJECT(m_pBorder);
}
std::string CAnnot::DictLookupString(Object* pObj, const char* sName, int nByte)
{
std::string sRes;
Object oObj;
if (pObj->dictLookup(sName, &oObj)->isString())
{
m_unFlags |= (1 << nByte);
TextString* s = new TextString(oObj.getString());
sRes = NSStringExt::CConverter::GetUtf8FromUTF32(s->getUnicode(), s->getLength());
delete s;
}
oObj.free();
return sRes;
}
//------------------------------------------------------------------------
// AP
//------------------------------------------------------------------------
CAnnotAP::CAnnotAP(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, const char* sView, const char* sButtonView, AcroFormField* pField, int nStartRefID)
{
m_gfx = NULL;
m_pFrame = NULL;
m_pRendererOut = NULL;
m_pRenderer = NULL;
m_dRWScale = 1;
m_dRHScale = 1;
m_bIsStamp = false;
Object oAP;
if (pField->fieldLookup("AP", &oAP)->isDict() && oAP.dictGetLength())
{
// Номер аннотации для сопоставления с AP
Object oRef;
pField->getFieldRef(&oRef);
m_unRefNum = oRef.getRefNum() + nStartRefID;
oRef.free();
// Координаты - BBox
pField->getBBox(&m_dx1, &m_dy1, &m_dx2, &m_dy2);
if (std::abs(m_dx2 - m_dx1) * std::abs(m_dy2 - m_dy1) < 1073741824.0 / 3.0)
{
Init(pdfDoc, pFontManager, pFontList, nRasterW, nRasterH, nBackgroundColor, nPageIndex);
Draw(pdfDoc, &oAP, nRasterH, nBackgroundColor, nPageIndex, pField, sView, sButtonView);
}
}
oAP.free();
Clear();
}
CAnnotAP::CAnnotAP(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex, const char* sView, Object* oAnnotRef, int nStartRefID)
{
m_gfx = NULL;
m_pFrame = NULL;
m_pRendererOut = NULL;
m_pRenderer = NULL;
m_dRWScale = 1;
m_dRHScale = 1;
Object oAnnot, oAP, oSubtype;
XRef* xref = pdfDoc->getXRef();
oAnnotRef->fetch(xref, &oAnnot);
m_bIsStamp = oAnnot.dictLookup("Subtype", &oSubtype)->isName("Stamp") == gTrue;
if (oAnnot.dictLookup("AP", &oAP)->isDict())
{
m_unRefNum = oAnnotRef->getRefNum() + nStartRefID;
Init(&oAnnot);
if (std::abs(m_dx2 - m_dx1) * std::abs(m_dy2 - m_dy1) < 1073741824.0 / 3.0)
{
Init(pdfDoc, pFontManager, pFontList, nRasterW, nRasterH, nBackgroundColor, nPageIndex);
Draw(pdfDoc, &oAP, nRasterH, nBackgroundColor, oAnnotRef, sView);
}
}
oAP.free(); oAnnot.free(); oSubtype.free();
Clear();
}
CAnnotAP::~CAnnotAP()
{
Clear();
for (int i = 0; i < m_arrAP.size(); ++i)
{
RELEASEOBJECT(m_arrAP[i]);
}
}
void CAnnotAP::Clear()
{
RELEASEOBJECT(m_gfx);
RELEASEOBJECT(m_pFrame);
RELEASEOBJECT(m_pRendererOut);
RELEASEOBJECT(m_pRenderer);
}
void CAnnotAP::Init(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex)
{
Page* pPage = pdfDoc->getCatalog()->getPage(nPageIndex);
PDFRectangle* pCropBox = pPage->getCropBox();
m_dCropX = pCropBox->x1;
m_dCropY = pCropBox->y1;
double dWidth = round(pdfDoc->getPageCropWidth(nPageIndex));
double dHeight = round(pdfDoc->getPageCropHeight(nPageIndex));
double dRasterW = (double)nRasterW * m_dRWScale;
double dRasterH = (double)nRasterH * m_dRHScale;
m_dWScale = dRasterW / dWidth;
m_dHScale = dRasterH / dHeight;
m_nWidth = (int)round((m_dx2 - m_dx1) * m_dWScale);
m_nHeight = (int)round((m_dy2 - m_dy1) * m_dHScale);
m_dWTale = m_nWidth - (m_dx2 - m_dx1) * m_dWScale;
m_dHTale = m_nHeight - (m_dy2 - m_dy1) * m_dHScale;
m_nWidth += 2;
m_nHeight += 2;
// Отрисовка на прозрачном холсте с заданым цветом фона
BYTE* pBgraData = new BYTE[m_nWidth * m_nHeight * 4];
unsigned int nColor = (unsigned int)nBackgroundColor;
unsigned int nSize = (unsigned int)(m_nWidth * m_nHeight);
unsigned int* pTemp = (unsigned int*)pBgraData;
for (unsigned int i = 0; i < nSize; ++i)
*pTemp++ = nColor;
m_pFrame = new CBgraFrame();
m_pFrame->put_Data(pBgraData);
m_pFrame->put_Width(m_nWidth);
m_pFrame->put_Height(m_nHeight);
m_pFrame->put_Stride(4 * m_nWidth);
m_pRenderer = NSGraphics::Create();
m_pRenderer->SetFontManager(pFontManager);
m_pRenderer->CreateFromBgraFrame(m_pFrame);
m_pRenderer->SetSwapRGB(true);
m_pRenderer->put_Width ((m_dx2 - m_dx1 + (2 + m_dWTale) * dWidth / dRasterW) * 25.4 / 72.0);
m_pRenderer->put_Height((m_dy2 - m_dy1 + (2 + m_dHTale) * dHeight / dRasterH) * 25.4 / 72.0);
if (nBackgroundColor != 0xFFFFFF)
m_pRenderer->CommandLong(c_nDarkMode, 1);
m_pRenderer->CommandLong(c_nPenWidth0As1px, 1);
m_pRendererOut = new RendererOutputDev(m_pRenderer, pFontManager, pFontList);
m_pRendererOut->NewPDF(pdfDoc->getXRef());
// Создание Gfx
GBool crop = gTrue;
PDFRectangle box;
// Поворот не требуется
pPage->makeBox(72.0, 72.0, 0, gFalse, m_pRendererOut->upsideDown(), -1, -1, -1, -1, &box, &crop);
PDFRectangle* cropBox = pPage->getCropBox();
m_gfx = new Gfx(pdfDoc, m_pRendererOut, nPageIndex, pPage->getAttrs()->getResourceDict(), 72.0, 72.0, &box, crop ? cropBox : (PDFRectangle *)NULL, 0, NULL, NULL);
// Координаты внешнего вида
m_dRx1 = (m_dx1 - m_dCropX) * m_dWScale - 1;
m_dRy1 = (pdfDoc->getPageCropHeight(nPageIndex) - m_dy2 + m_dCropY) * m_dHScale - 1;
}
void CAnnotAP::Init(Object* oAnnot)
{
Object oObj, oObj2;
if (oAnnot->dictLookup("Rect", &oObj)->isArray() && oObj.arrayGetLength() == 4)
{
m_dx1 = ArrGetNum(&oObj, 0);
m_dy1 = ArrGetNum(&oObj, 1);
m_dx2 = ArrGetNum(&oObj, 2);
m_dy2 = ArrGetNum(&oObj, 3);
if (m_bIsStamp)
{
double m[6] = { 1, 0, 0, 1, 0, 0 }, bbox[4] = { m_dx1, m_dy1, m_dx2, m_dy2 };
oObj.free();
Object oAP;
if (oAnnot->dictLookup("AP", &oAP)->isDict() && oAP.dictLookup("N", &oObj2)->isStream())
{
Object oObj1;
if (oObj2.streamGetDict()->lookup("BBox", &oObj)->isArray() && oObj.arrayGetLength() == 4)
{
for (int i = 0; i < 4; ++i)
{
oObj.arrayGet(i, &oObj1);
bbox[i] = oObj1.isNum() ? oObj1.getNum() : 0;
oObj1.free();
}
}
oObj.free();
if (oObj2.streamGetDict()->lookup("Matrix", &oObj)->isArray() && oObj.arrayGetLength() == 6)
{
for (int i = 0; i < 6; ++i)
{
oObj.arrayGet(i, &oObj1);
m[i] = oObj1.getNum();
oObj1.free();
}
}
}
oAP.free(); oObj2.free();
double formXMin, formYMin, formXMax, formYMax, x, y, sx, sy;
x = bbox[0] * m[0] + bbox[1] * m[2] + m[4];
y = bbox[0] * m[1] + bbox[1] * m[3] + m[5];
formXMin = formXMax = x;
formYMin = formYMax = y;
x = bbox[0] * m[0] + bbox[3] * m[2] + m[4];
y = bbox[0] * m[1] + bbox[3] * m[3] + m[5];
if (x < formXMin)
formXMin = x;
else if (x > formXMax)
formXMax = x;
if (y < formYMin)
formYMin = y;
else if (y > formYMax)
formYMax = y;
x = bbox[2] * m[0] + bbox[1] * m[2] + m[4];
y = bbox[2] * m[1] + bbox[1] * m[3] + m[5];
if (x < formXMin)
formXMin = x;
else if (x > formXMax)
formXMax = x;
if (y < formYMin)
formYMin = y;
else if (y > formYMax)
formYMax = y;
x = bbox[2] * m[0] + bbox[3] * m[2] + m[4];
y = bbox[2] * m[1] + bbox[3] * m[3] + m[5];
if (x < formXMin)
formXMin = x;
else if (x > formXMax)
formXMax = x;
if (y < formYMin)
formYMin = y;
else if (y > formYMax)
formYMax = y;
if (formXMin == formXMax)
sx = 1;
else
sx = (m_dx2 - m_dx1) / (formXMax - formXMin);
if (formYMin == formYMax)
sy = 1;
else
sy = (m_dy2 - m_dy1) / (formYMax - formYMin);
m_dx1 = bbox[0];
m_dy1 = bbox[1];
m_dx2 = bbox[2];
m_dy2 = bbox[3];
m_dRWScale = sx;
m_dRHScale = sy;
}
double dTemp;
if (m_dx1 > m_dx2)
{
dTemp = m_dx1; m_dx1 = m_dx2; m_dx2 = dTemp;
}
if (m_dy1 > m_dy2)
{
dTemp = m_dy1; m_dy1 = m_dy2; m_dy2 = dTemp;
}
}
oObj.free();
}
void CAnnotAP::Draw(PDFDoc* pdfDoc, Object* oAP, int nRasterH, int nBackgroundColor, int nPageIndex, AcroFormField* pField, const char* sView, const char* sButtonView)
{
// Отрисовка внешних видов аннотации
AcroFormFieldType oType = pField->getAcroFormFieldType();
((GlobalParamsAdaptor*)globalParams)->setDrawFormField(true);
double dOffsetX = -(m_dx1 - m_dCropX) * m_dWScale + 1 + m_dWTale / 2;
double dOffsetY = (m_dy2 - m_dCropY) * m_dHScale - nRasterH + 1 + m_dHTale / 2;
std::vector<const char*> arrAPName { "N", "D", "R" };
for (unsigned int j = 0; j < arrAPName.size(); ++j)
{
if (sView && strcmp(sView, arrAPName[j]) != 0)
continue;
Object oObj;
if (oAP->dictLookup(arrAPName[j], &oObj)->isDict())
{
for (int k = 0; k < oObj.dictGetLength(); ++k)
{
if (sButtonView)
{
if (strcmp(sButtonView, "Off") == 0 && strcmp(oObj.dictGetKey(k), "Off") != 0)
continue;
if (strcmp(sButtonView, "Yes") == 0 && strcmp(oObj.dictGetKey(k), "Off") == 0)
continue;
}
CAnnotAPView* pView = new CAnnotAPView();
pView->sAPName = arrAPName[j];
pView->sASName = oObj.dictGetKey(k);
if ((oType == acroFormFieldRadioButton || oType == acroFormFieldCheckbox) && pView->sASName != "Off")
pView->sASName = "Yes";
m_pRenderer->SetCoordTransformOffset(dOffsetX, dOffsetY);
DrawAppearance(pdfDoc, nPageIndex, pField, m_gfx, arrAPName[j], pView->sASName.c_str());
WriteAppearance(nBackgroundColor, pView);
pView->nBlendMode = GetBlendMode();
m_arrAP.push_back(pView);
}
}
else if (!oObj.isNull())
{
CAnnotAPView* pView = new CAnnotAPView();
pView->sAPName = arrAPName[j];
m_pRenderer->SetCoordTransformOffset(dOffsetX, dOffsetY);
DrawAppearance(pdfDoc, nPageIndex, pField, m_gfx, arrAPName[j], NULL);
WriteAppearance(nBackgroundColor, pView);
pView->nBlendMode = GetBlendMode();
m_arrAP.push_back(pView);
}
oObj.free();
}
((GlobalParamsAdaptor*)globalParams)->setDrawFormField(false);
}
void CAnnotAP::Draw(PDFDoc* pdfDoc, Object* oAP, int nRasterH, int nBackgroundColor, Object* oAnnotRef, const char* sView)
{
((GlobalParamsAdaptor*)globalParams)->setDrawFormField(true);
// Отрисовка внешних видов аннотации
Object oAnnot;
XRef* xref = pdfDoc->getXRef();
oAnnotRef->fetch(xref, &oAnnot);
double dOffsetX = -(m_dx1 - m_dCropX) * m_dWScale + 1 + m_dWTale / 2;
double dOffsetY = (m_dy2 - m_dCropY) * m_dHScale - (double)nRasterH * m_dRHScale + 1 + m_dHTale / 2;
std::vector<const char*> arrAPName { "N", "D", "R" };
for (unsigned int j = 0; j < arrAPName.size(); ++j)
{
if (sView && strcmp(sView, arrAPName[j]) != 0)
continue;
Object oObj;
if (oAP->dictLookup(arrAPName[j], &oObj)->isStream())
{
CAnnotAPView* pView = new CAnnotAPView();
pView->sAPName = arrAPName[j];
m_pRenderer->SetCoordTransformOffset(dOffsetX, dOffsetY);
Ref ref = oAnnotRef->getRef();
Annot* annot = new Annot(pdfDoc, oAnnot.getDict(), &ref, arrAPName[j]);
if (annot)
{
annot->generateAnnotAppearance();
annot->draw(m_gfx, gFalse);
}
RELEASEOBJECT(annot);
WriteAppearance(nBackgroundColor, pView);
pView->nBlendMode = GetBlendMode();
m_arrAP.push_back(pView);
}
oObj.free();
}
oAnnot.free();
((GlobalParamsAdaptor*)globalParams)->setDrawFormField(false);
}
void CAnnotAP::WriteAppearance(unsigned int nColor, CAnnotAPView* pView)
{
BYTE* pSubMatrix = new BYTE[m_nWidth * m_nHeight * 4];
int p = 0;
unsigned int* pTemp = (unsigned int*)m_pFrame->get_Data();
unsigned int* pSubTemp = (unsigned int*)pSubMatrix;
for (int y = 0; y < m_nHeight; ++y)
{
for (int x = 0; x < m_nWidth; ++x)
{
pSubTemp[p++] = pTemp[y * m_nWidth + x];
pTemp[y * m_nWidth + x] = nColor;
}
}
pView->pAP = pSubMatrix;
}
BYTE CAnnotAP::GetBlendMode()
{
return 0;
}
//------------------------------------------------------------------------
// ToWASM
//------------------------------------------------------------------------
void CAnnotAP::ToWASM(NSWasm::CData& oRes)
{
if (m_arrAP.empty())
return;
oRes.AddInt(m_unRefNum);
oRes.AddDouble(m_dRx1);
oRes.AddDouble(m_dRy1);
oRes.AddInt(m_nWidth);
oRes.AddInt(m_nHeight);
oRes.AddInt((unsigned int)m_arrAP.size());
for (int i = 0; i < m_arrAP.size(); ++i)
{
oRes.WriteString(m_arrAP[i]->sAPName);
oRes.WriteString(m_arrAP[i]->sASName);
unsigned long long npSubMatrix = (unsigned long long)m_arrAP[i]->pAP;
unsigned int npSubMatrix1 = npSubMatrix & 0xFFFFFFFF;
oRes.AddInt(npSubMatrix1);
oRes.AddInt(npSubMatrix >> 32);
oRes.WriteBYTE(m_arrAP[i]->nBlendMode);
}
}
void CAnnots::ToWASM(NSWasm::CData& oRes)
{
// Порядок вычислений - CO
oRes.AddInt(m_arrCO.size());
for (int i = 0; i < m_arrCO.size(); ++i)
oRes.AddInt(m_arrCO[i]);
// Родительские Fields
oRes.AddInt(m_arrParents.size());
for (int i = 0; i < m_arrParents.size(); ++i)
m_arrParents[i]->ToWASM(oRes);
oRes.AddInt(m_arrAnnots.size());
for (int i = 0; i < m_arrAnnots.size(); ++i)
m_arrAnnots[i]->ToWASM(oRes);
}
void CAnnots::CAnnotParent::ToWASM(NSWasm::CData& oRes)
{
oRes.AddInt(unRefNum);
oRes.AddInt(unFlags);
if (unFlags & (1 << 0))
oRes.WriteString(sT);
if (unFlags & (1 << 1))
oRes.WriteString(sV);
if (unFlags & (1 << 2))
oRes.WriteString(sDV);
if (unFlags & (1 << 3))
{
oRes.AddInt((unsigned int)arrI.size());
for (int i = 0; i < arrI.size(); ++i)
oRes.AddInt(arrI[i]);
}
if (unFlags & (1 << 4))
oRes.AddInt(unRefNumParent);
if (unFlags & (1 << 5))
{
oRes.AddInt((unsigned int)arrV.size());
for (int i = 0; i < arrV.size(); ++i)
oRes.WriteString(arrV[i]);
}
if (unFlags & (1 << 6))
{
oRes.AddInt(arrOpt.size());
for (int i = 0; i < arrOpt.size(); ++i)
{
oRes.WriteString(arrOpt[i].first);
oRes.WriteString(arrOpt[i].second);
}
}
if (unFlags & (1 << 7))
oRes.AddInt(unFieldFlag);
if (unFlags & (1 << 8))
{
oRes.AddInt(arrAction.size());
for (int i = 0; i < arrAction.size(); ++i)
{
oRes.WriteString(arrAction[i]->sType);
arrAction[i]->ToWASM(oRes);
}
}
if (unFlags & (1 << 9))
oRes.AddInt(unMaxLen);
if (unFlags & (1 << 10))
oRes.WriteString(sTU);
if (unFlags & (1 << 11))
oRes.AddInt(unMEOptions);
}
void CAnnot::ToWASM(NSWasm::CData& oRes)
{
oRes.AddInt(m_unRefNum);
oRes.AddInt(m_unAnnotFlag);
oRes.AddInt(m_unPage - 1);
for (int i = 0; i < 4; ++i)
oRes.WriteDouble(m_pRect[i]);
oRes.AddInt(m_unAFlags);
if (m_unAFlags & (1 << 0))
oRes.WriteString(m_sNM);
if (m_unAFlags & (1 << 1))
oRes.WriteString(m_sContents);
if (m_unAFlags & (1 << 2))
{
oRes.WriteBYTE(m_pBE.first);
oRes.AddDouble(m_pBE.second);
}
if (m_unAFlags & (1 << 3))
{
oRes.AddInt((unsigned int)m_arrC.size());
for (int i = 0; i < m_arrC.size(); ++i)
oRes.WriteDouble(m_arrC[i]);
}
if (m_pBorder && (m_unAFlags & (1 << 4)))
m_pBorder->ToWASM(oRes);
if (m_unAFlags & (1 << 5))
oRes.WriteString(m_sM);
if (m_unAFlags & (1 << 7))
oRes.WriteString(m_sOUserID);
if (m_unAFlags & (1 << 9))
oRes.WriteString(m_sOMetadata);
}
void CAnnot::CBorderType::ToWASM(NSWasm::CData& oRes)
{
BYTE nBP = nType;
if (nBP == 1)
nBP = 2;
else if (nBP == 2)
nBP = 1;
oRes.WriteBYTE(nBP);
oRes.AddDouble(dWidth);
if (nType == annotBorderDashed)
{
oRes.AddInt(arrDash.size());
for (int i = 0; i < arrDash.size(); ++i)
oRes.AddDouble(arrDash[i]);
}
}
void CAnnotWidget::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(m_nType);
CAnnot::ToWASM(oRes);
oRes.WriteString(m_sFontName);
oRes.AddDouble(m_dFontSize);
oRes.AddInt(m_unFontStyle);
oRes.AddInt(m_arrTC.size());
for (int i = 0; i < m_arrTC.size(); ++i)
oRes.WriteDouble(m_arrTC[i]);
oRes.WriteBYTE(m_nQ);
oRes.AddInt(m_unFieldFlag);
oRes.AddInt(m_unFlags);
if (m_unFlags & (1 << 0))
oRes.WriteString(m_sTU);
if (m_unFlags & (1 << 1))
oRes.WriteString(m_sDS);
if (m_unFlags & (1 << 2))
oRes.WriteString(m_sActualFontName);
if (m_unFlags & (1 << 3))
oRes.WriteBYTE(m_nH);
if (m_unFlags & (1 << 4))
oRes.WriteString(m_sFontKey);
if (m_unFlags & (1 << 5))
{
oRes.AddInt(m_arrBC.size());
for (int i = 0; i < m_arrBC.size(); ++i)
oRes.WriteDouble(m_arrBC[i]);
}
if (m_unFlags & (1 << 6))
oRes.AddInt(m_unR);
if (m_unFlags & (1 << 7))
{
oRes.AddInt(m_arrBG.size());
for (int i = 0; i < m_arrBG.size(); ++i)
oRes.WriteDouble(m_arrBG[i]);
}
if (m_unFlags & (1 << 8))
oRes.WriteString(m_sDV);
if (m_unFlags & (1 << 17))
oRes.AddInt(m_unRefNumParent);
if (m_unFlags & (1 << 18))
oRes.WriteString(m_sT);
if (m_unFlags & (1 << 19))
oRes.WriteString(m_sButtonFontName);
if (m_unFlags & (1 << 21))
oRes.AddInt(m_unMEOptions);
oRes.AddInt(m_arrAction.size());
for (int i = 0; i < m_arrAction.size(); ++i)
{
oRes.WriteString(m_arrAction[i]->sType);
m_arrAction[i]->ToWASM(oRes);
}
}
void CActionGoTo::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(1);
oRes.AddInt(unPage);
oRes.WriteBYTE(nKind);
switch (nKind)
{
case destXYZ:
case destFitH:
case destFitBH:
case destFitV:
case destFitBV:
{
oRes.WriteBYTE(unKindFlag);
if (unKindFlag & (1 << 0))
oRes.AddDouble(pRect[0]);
if (unKindFlag & (1 << 1))
oRes.AddDouble(pRect[1]);
if (unKindFlag & (1 << 2))
oRes.AddDouble(pRect[3]);
break;
}
case destFitR:
{
oRes.AddDouble(pRect[0]);
oRes.AddDouble(pRect[1]);
oRes.AddDouble(pRect[2]);
oRes.AddDouble(pRect[3]);
break;
}
case destFit:
case destFitB:
default:
break;
}
CAction::ToWASM(oRes);
}
void CActionURI::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(6);
oRes.WriteString(sURI);
CAction::ToWASM(oRes);
}
void CActionNamed::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(10);
oRes.WriteString(sNamed);
CAction::ToWASM(oRes);
}
void CActionJavaScript::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(14);
oRes.WriteString(sJavaScript);
CAction::ToWASM(oRes);
}
void CActionHide::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(9);
oRes.WriteBYTE(bHideFlag ? 1 : 0);
oRes.AddInt(arrAnnotName.size());
for (int i = 0; i < arrAnnotName.size(); ++i)
oRes.WriteString(arrAnnotName[i]);
CAction::ToWASM(oRes);
}
void CActionResetForm::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(12);
oRes.AddInt(unFlags);
oRes.AddInt(arrAnnotName.size());
for (int i = 0; i < arrAnnotName.size(); ++i)
oRes.WriteString(arrAnnotName[i]);
CAction::ToWASM(oRes);
}
void CAction::ToWASM(NSWasm::CData& oRes)
{
if (pNext)
{
oRes.WriteBYTE(1);
pNext->ToWASM(oRes);
}
else
oRes.WriteBYTE(0);
}
void CAnnotWidgetBtn::ToWASM(NSWasm::CData& oRes)
{
CAnnotWidget::ToWASM(oRes);
if (m_unFlags & (1 << 9))
oRes.WriteString(m_sV);
if (m_nType == 27)
{
oRes.AddInt(m_unIFFlag);
if (m_unFlags & (1 << 10))
oRes.WriteString(m_sCA);
if (m_unFlags & (1 << 11))
oRes.WriteString(m_sRC);
if (m_unFlags & (1 << 12))
oRes.WriteString(m_sAC);
if (m_unFlags & (1 << 13))
oRes.WriteBYTE(m_nTP);
if (m_unIFFlag & (1 << 0))
{
if (m_unIFFlag & (1 << 1))
oRes.WriteBYTE(m_nSW);
if (m_unIFFlag & (1 << 2))
oRes.WriteBYTE(m_nS);
if (m_unIFFlag & (1 << 3))
{
oRes.AddDouble(m_dA1);
oRes.AddDouble(m_dA2);
}
}
}
else
{
oRes.WriteBYTE(m_nStyle);
if (m_unFlags & (1 << 14))
oRes.WriteString(m_sAP_N_Yes);
}
}
void CAnnotWidgetTx::ToWASM(NSWasm::CData& oRes)
{
CAnnotWidget::ToWASM(oRes);
if (m_unFlags & (1 << 9))
oRes.WriteString(m_sV);
if (m_unFlags & (1 << 10))
oRes.AddInt(m_unMaxLen);
if (m_unFlags & (1 << 11))
oRes.WriteString(m_sRV);
}
void CAnnotWidgetCh::ToWASM(NSWasm::CData& oRes)
{
CAnnotWidget::ToWASM(oRes);
if (m_unFlags & (1 << 9))
oRes.WriteString(m_sV);
if (m_unFlags & (1 << 10))
{
oRes.AddInt(m_arrOpt.size());
for (int i = 0; i < m_arrOpt.size(); ++i)
{
oRes.WriteString(m_arrOpt[i].first);
oRes.WriteString(m_arrOpt[i].second);
}
}
if (m_unFlags & (1 << 11))
oRes.AddInt(m_unTI);
if (m_unFlags & (1 << 12))
{
oRes.AddInt(m_arrI.size());
for (int i = 0; i < m_arrI.size(); ++i)
oRes.AddInt(m_arrI[i]);
}
if (m_unFlags & (1 << 13))
{
oRes.AddInt(m_arrV.size());
for (int i = 0; i < m_arrV.size(); ++i)
oRes.WriteString(m_arrV[i]);
}
}
void CAnnotWidgetSig::ToWASM(NSWasm::CData& oRes)
{
CAnnotWidget::ToWASM(oRes);
}
void CAnnotMarkup::ToWASM(NSWasm::CData& oRes)
{
CAnnot::ToWASM(oRes);
oRes.AddInt(m_unFlags);
if (m_unFlags & (1 << 0))
oRes.AddInt(m_unRefNumPopup);
if (m_unFlags & (1 << 1))
oRes.WriteString(m_sT);
if (m_unFlags & (1 << 2))
oRes.AddDouble(m_dCA);
if (m_unFlags & (1 << 3))
{
oRes.AddInt(m_arrRC.size());
for (int i = 0; i < m_arrRC.size(); ++i)
{
oRes.WriteBYTE(m_arrRC[i]->nAlign);
oRes.AddInt(m_arrRC[i]->unFontFlags);
if (m_arrRC[i]->unFontFlags & (1 << 5))
oRes.AddDouble(m_arrRC[i]->dVAlign);
if (m_arrRC[i]->unFontFlags & (1 << 6))
oRes.WriteString(m_arrRC[i]->sActualFont);
oRes.AddDouble(m_arrRC[i]->dFontSise);
oRes.WriteDouble(m_arrRC[i]->dColor[0]);
oRes.WriteDouble(m_arrRC[i]->dColor[1]);
oRes.WriteDouble(m_arrRC[i]->dColor[2]);
oRes.WriteString(m_arrRC[i]->sFontFamily);
oRes.WriteString(m_arrRC[i]->sText);
}
}
if (m_unFlags & (1 << 4))
oRes.WriteString(m_sCreationDate);
if (m_unFlags & (1 << 5))
oRes.AddInt(m_unRefNumIRT);
if (m_unFlags & (1 << 6))
oRes.WriteBYTE(m_nRT);
if (m_unFlags & (1 << 7))
oRes.WriteString(m_sSubj);
}
void CAnnotText::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(0); // Text
CAnnotMarkup::ToWASM(oRes);
if (m_unFlags & (1 << 16))
oRes.WriteBYTE(m_nName);
if (m_unFlags & (1 << 17))
oRes.WriteBYTE(m_nStateModel);
if (m_unFlags & (1 << 18))
oRes.WriteBYTE(m_nState);
}
void CAnnotPopup::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(15); // Popup
CAnnot::ToWASM(oRes);
oRes.AddInt(m_unFlags);
if (m_unFlags & (1 << 1))
oRes.AddInt(m_unRefNumParent);
}
void CAnnotInk::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(14); // Ink
CAnnotMarkup::ToWASM(oRes);
oRes.AddInt(m_arrInkList.size());
for (int i = 0; i < m_arrInkList.size(); ++i)
{
oRes.AddInt(m_arrInkList[i].size());
for (int j = 0; j < m_arrInkList[i].size(); ++j)
oRes.AddDouble(m_arrInkList[i][j]);
}
}
void CAnnotLine::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(3); // Line
CAnnotMarkup::ToWASM(oRes);
for (int i = 0; i < 4; ++i)
oRes.AddDouble(m_pL[i]);
if (m_unFlags & (1 << 15))
{
oRes.WriteBYTE(m_nLE[0]);
oRes.WriteBYTE(m_nLE[1]);
}
if (m_unFlags & (1 << 16))
{
oRes.AddInt((unsigned int)m_arrIC.size());
for (int i = 0; i < m_arrIC.size(); ++i)
oRes.WriteDouble(m_arrIC[i]);
}
if (m_unFlags & (1 << 17))
oRes.AddDouble(m_dLL);
if (m_unFlags & (1 << 18))
oRes.AddDouble(m_dLLE);
if (m_unFlags & (1 << 20))
oRes.WriteBYTE(m_nIT);
if (m_unFlags & (1 << 21))
oRes.AddDouble(m_dLLO);
if (m_unFlags & (1 << 22))
oRes.WriteBYTE(m_nCP);
if (m_unFlags & (1 << 23))
{
oRes.AddDouble(m_pCO[0]);
oRes.AddDouble(m_pCO[1]);
}
}
void CAnnotTextMarkup::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(m_nSubtype); // Highlight, Underline, Squiggly, StrikeOut
CAnnotMarkup::ToWASM(oRes);
oRes.AddInt((unsigned int)m_arrQuadPoints.size());
for (int i = 0; i < m_arrQuadPoints.size(); ++i)
oRes.AddDouble(m_arrQuadPoints[i]);
}
void CAnnotSquareCircle::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(m_nSubtype); // Square, Circle
CAnnotMarkup::ToWASM(oRes);
if (m_unFlags & (1 << 15))
{
for (int i = 0; i < 4; ++i)
oRes.AddDouble(m_pRD[i]);
}
if (m_unFlags & (1 << 16))
{
oRes.AddInt((unsigned int)m_arrIC.size());
for (int i = 0; i < m_arrIC.size(); ++i)
oRes.WriteDouble(m_arrIC[i]);
}
}
void CAnnotPolygonLine::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(m_nSubtype); // Polygon, PolyLine
CAnnotMarkup::ToWASM(oRes);
oRes.AddInt((unsigned int)m_arrVertices.size());
for (int i = 0; i < m_arrVertices.size(); ++i)
oRes.AddDouble(m_arrVertices[i]);
if (m_unFlags & (1 << 15))
{
oRes.WriteBYTE(m_nLE[0]);
oRes.WriteBYTE(m_nLE[1]);
}
if (m_unFlags & (1 << 16))
{
oRes.AddInt((unsigned int)m_arrIC.size());
for (int i = 0; i < m_arrIC.size(); ++i)
oRes.WriteDouble(m_arrIC[i]);
}
if (m_unFlags & (1 << 20))
oRes.WriteBYTE(m_nIT);
}
void CAnnotFreeText::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(2); // FreeText
CAnnotMarkup::ToWASM(oRes);
oRes.WriteBYTE(m_nQ);
oRes.AddInt(m_nRotate);
if (m_unFlags & (1 << 15))
{
for (int i = 0; i < 4; ++i)
oRes.AddDouble(m_pRD[i]);
}
if (m_unFlags & (1 << 16))
{
oRes.AddInt((unsigned int)m_arrCL.size());
for (int i = 0; i < m_arrCL.size(); ++i)
oRes.AddDouble(m_arrCL[i]);
}
if (m_unFlags & (1 << 17))
oRes.WriteString(m_sDS);
if (m_unFlags & (1 << 18))
oRes.WriteBYTE(m_nLE);
if (m_unFlags & (1 << 20))
oRes.WriteBYTE(m_nIT);
if (m_unFlags & (1 << 21))
{
oRes.AddInt((unsigned int)m_arrCFromDA.size());
for (int i = 0; i < m_arrCFromDA.size(); ++i)
oRes.WriteDouble(m_arrCFromDA[i]);
}
}
void CAnnotCaret::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(13); // Caret
CAnnotMarkup::ToWASM(oRes);
if (m_unFlags & (1 << 15))
{
for (int i = 0; i < 4; ++i)
oRes.AddDouble(m_pRD[i]);
}
if (m_unFlags & (1 << 16))
oRes.WriteBYTE(m_nSy);
}
void CAnnotFileAttachment::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(16); // FileAttachment
CAnnotMarkup::ToWASM(oRes);
if (m_unFlags & (1 << 15))
oRes.WriteString(m_sName);
if (m_unFlags & (1 << 16))
oRes.WriteString(m_sFS);
if (m_unFlags & (1 << 17))
oRes.WriteString(m_sF);
if (m_unFlags & (1 << 18))
oRes.WriteString(m_sUF);
if (m_unFlags & (1 << 19))
oRes.WriteString(m_sDOS);
if (m_unFlags & (1 << 20))
oRes.WriteString(m_sMac);
if (m_unFlags & (1 << 21))
oRes.WriteString(m_sUnix);
if (m_unFlags & (1 << 22))
{
oRes.WriteString(m_sID.first);
oRes.WriteString(m_sID.second);
}
if (m_unFlags & (1 << 24))
{
int nFlag = 0;
int nPos = oRes.GetSize();
oRes.AddInt(nFlag);
auto fWriteEF = [&oRes](CAnnotFileAttachment::CEmbeddedFile* pEF)
{
oRes.AddInt(pEF->nLength);
unsigned long long npSubMatrix = (unsigned long long)pEF->pFile;
unsigned int npSubMatrix1 = npSubMatrix & 0xFFFFFFFF;
oRes.AddInt(npSubMatrix1);
oRes.AddInt(npSubMatrix >> 32);
pEF->bFree = false;
};
// Освобождение памяти необходимо вызвать с js стороны
if (m_pEF->m_pF)
{
nFlag |= (1 << 0);
fWriteEF(m_pEF->m_pF);
}
if (m_pEF->m_pUF)
{
nFlag |= (1 << 1);
fWriteEF(m_pEF->m_pUF);
}
if (m_pEF->m_pDOS)
{
nFlag |= (1 << 2);
fWriteEF(m_pEF->m_pDOS);
}
if (m_pEF->m_pMac)
{
nFlag |= (1 << 3);
fWriteEF(m_pEF->m_pMac);
}
if (m_pEF->m_pUnix)
{
nFlag |= (1 << 4);
fWriteEF(m_pEF->m_pUnix);
}
oRes.AddInt(nFlag, nPos);
}
if (m_unFlags & (1 << 25))
{
}
if (m_unFlags & (1 << 26))
oRes.WriteString(m_sDesc);
if (m_unFlags & (1 << 27))
{
}
}
void CAnnotStamp::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(12); // Stamp
CAnnotMarkup::ToWASM(oRes);
oRes.WriteString(m_sName);
oRes.WriteDouble(m_dRotate);
oRes.WriteDouble(m_dX1);
oRes.WriteDouble(m_dY1);
oRes.WriteDouble(m_dX2);
oRes.WriteDouble(m_dY2);
oRes.WriteDouble(m_dX3);
oRes.WriteDouble(m_dY3);
oRes.WriteDouble(m_dX4);
oRes.WriteDouble(m_dY4);
}
void CAnnotRedact::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(25); // Redact
CAnnotMarkup::ToWASM(oRes);
if (m_unFlags & (1 << 15))
{
oRes.AddInt((unsigned int)m_arrQuadPoints.size());
for (int i = 0; i < m_arrQuadPoints.size(); ++i)
oRes.AddDouble(m_arrQuadPoints[i]);
}
if (m_unFlags & (1 << 16))
{
oRes.AddInt((unsigned int)m_arrIC.size());
for (int i = 0; i < m_arrIC.size(); ++i)
oRes.WriteDouble(m_arrIC[i]);
}
if (m_unFlags & (1 << 17))
oRes.WriteString(m_sOverlayText);
if (m_unFlags & (1 << 19))
oRes.WriteBYTE(m_nQ);
if (m_unFlags & (1 << 20))
{
oRes.AddInt((unsigned int)m_arrCFromDA.size());
for (int i = 0; i < m_arrCFromDA.size(); ++i)
oRes.WriteDouble(m_arrCFromDA[i]);
oRes.AddDouble(m_dFontSize);
oRes.WriteString(m_sFontName);
oRes.WriteString(m_sActualFontName);
oRes.AddInt(m_unFontStyle);
}
}
}