mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 06:22:44 +08:00
Also checked: Common/3dParty/html/htmltoxhtml.cpp DesktopEditor/doctrenderer/drawingfile.h DjVuFile EpubFile Fb2File HtmlFile2/htmlfile2.cpp PdfFile XpsFile
4253 lines
108 KiB
C++
4253 lines
108 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 "PdfFont.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;
|
|
}
|
|
CActionGoTo* getGoTo(PDFDoc* pdfDoc, LinkAction* oAct)
|
|
{
|
|
if (!oAct || oAct->getKind() != actionGoTo)
|
|
return NULL;
|
|
|
|
GString* str = ((LinkGoTo*)oAct)->getNamedDest();
|
|
LinkDest* pLinkDest = str ? pdfDoc->findDest(str) : ((LinkGoTo*)oAct)->getDest();
|
|
if (!pLinkDest)
|
|
return NULL;
|
|
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);
|
|
return ppRes;
|
|
}
|
|
CAction* getDest(PDFDoc* pdfDoc, Object* oDest)
|
|
{
|
|
LinkAction* oAct = LinkAction::parseDest(oDest);
|
|
if (!oAct)
|
|
return NULL;
|
|
|
|
CAction* pRes = getGoTo(pdfDoc, oAct);
|
|
|
|
RELEASEOBJECT(oAct);
|
|
return pRes;
|
|
}
|
|
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)
|
|
{
|
|
// Navigation within the file
|
|
case actionGoTo:
|
|
{
|
|
pRes = getGoTo(pdfDoc, oAct);
|
|
break;
|
|
}
|
|
// Navigation to external file
|
|
case actionGoToR:
|
|
{
|
|
break;
|
|
}
|
|
// Launch external application
|
|
case actionLaunch:
|
|
{
|
|
break;
|
|
}
|
|
// External link
|
|
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;
|
|
}
|
|
// Non-standard named actions
|
|
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;
|
|
}
|
|
// Movie playback
|
|
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;
|
|
}
|
|
// Form submission
|
|
case actionSubmitForm:
|
|
{
|
|
break;
|
|
}
|
|
// Hide annotations
|
|
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;
|
|
}
|
|
// Unknown action
|
|
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)
|
|
{
|
|
// Borders and 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);
|
|
|
|
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;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// 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 - Field value - 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();
|
|
|
|
AcroFormFieldType oType = pField->getAcroFormFieldType();
|
|
Object oOpt;
|
|
// 10 - List of values
|
|
if (oType != acroFormFieldPushbutton && 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();
|
|
|
|
Object oMK;
|
|
m_nStyle = (oType == acroFormFieldRadioButton ? 3 : 0);
|
|
if (pField->fieldLookup("MK", &oMK)->isDict())
|
|
{
|
|
if (oType == acroFormFieldPushbutton)
|
|
{
|
|
// 10 - Caption - CA
|
|
m_sCA = DictLookupString(&oMK, "CA", 10);
|
|
// 11 - Rollover caption - RC
|
|
m_sRC = DictLookupString(&oMK, "RC", 11);
|
|
// 12 - Alternate caption - AC
|
|
m_sAC = DictLookupString(&oMK, "AC", 12);
|
|
}
|
|
else
|
|
{
|
|
if (oMK.dictLookup("CA", &oObj)->isString())
|
|
{
|
|
std::string sCA(oObj.getString()->getCString());
|
|
|
|
if (sCA == "l") // circle
|
|
m_nStyle = 3;
|
|
else if (sCA == "4") // checkmark
|
|
m_nStyle = 0;
|
|
else if (sCA == "8") // cross
|
|
m_nStyle = 1;
|
|
else if (sCA == "u") // diamond
|
|
m_nStyle = 2;
|
|
else if (sCA == "n") // square
|
|
m_nStyle = 5;
|
|
else if (sCA == "H") // star
|
|
m_nStyle = 4;
|
|
}
|
|
oObj.free();
|
|
}
|
|
|
|
// 13 - Title position - 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 - Scaling - 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 - Scaling type - 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 - Offset - 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 - Full fit - FB
|
|
if (oIF.dictLookup("FB", &oObj)->isBool() && oObj.getBool())
|
|
m_unIFFlag |= (1 << 4);
|
|
oObj.free();
|
|
}
|
|
oIF.free();
|
|
}
|
|
oMK.free();
|
|
|
|
pField->fieldLookup("Opt", &oOpt);
|
|
|
|
// 14 - On state name - 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 - Value - V
|
|
if (oField.dictLookup("V", &oObj))
|
|
{
|
|
m_sV = getValue(&oObj);
|
|
if (!m_sV.empty())
|
|
m_unFlags |= (1 << 9);
|
|
}
|
|
oObj.free();
|
|
oField.free();
|
|
|
|
// 10 - Maximum number of characters in Tx - MaxLen
|
|
if (oField.dictLookup("MaxLen", &oObj)->isInt())
|
|
{
|
|
m_unFlags |= (1 << 10);
|
|
m_unMaxLen = oObj.getInt();
|
|
}
|
|
oObj.free();
|
|
|
|
// 11 - Rich text 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 - Value
|
|
if (oField.dictLookup("V", &oObj))
|
|
{
|
|
m_sV = getValue(&oObj, false);
|
|
if (!m_sV.empty())
|
|
m_unFlags |= (1 << 9);
|
|
}
|
|
oObj.free();
|
|
|
|
Object oOpt;
|
|
// 10 - List of values
|
|
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 - Top element index - TI
|
|
if (pField->fieldLookup("TI", &oObj)->isInt())
|
|
{
|
|
m_unFlags |= (1 << 11);
|
|
m_unTI = oObj.getInt();
|
|
}
|
|
oObj.free();
|
|
|
|
// 12 - Selected indices - 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 - Values array
|
|
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 - Value
|
|
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;
|
|
|
|
// Text color - from 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);
|
|
|
|
// Text alignment - Q
|
|
m_nQ = 0;
|
|
if (pField->fieldLookup("Q", &oObj)->isInt())
|
|
m_nQ = oObj.getInt();
|
|
oObj.free();
|
|
|
|
// Type - FT + flags
|
|
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;
|
|
}
|
|
|
|
// Flag - Ff
|
|
m_unFieldFlag = -1;
|
|
if (oField.dictLookup("Ff", &oObj)->isInt())
|
|
m_unFieldFlag = oObj.getInt();
|
|
oObj.free();
|
|
|
|
// 0 - Alternative field name, used in tooltips and error messages - TU
|
|
if (oField.dictLookup("TU", &oObj))
|
|
{
|
|
m_sTU = getValue(&oObj);
|
|
if (!m_sTU.empty())
|
|
m_unFlags |= (1 << 0);
|
|
}
|
|
oObj.free();
|
|
|
|
// 1 - Default style string - DS
|
|
m_sDS = FieldLookupString(pField, "DS", 1);
|
|
|
|
// 3 - Highlighting mode - 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 - Border color - BC. Even if border is not set by BS/Border, if BC is present a default border is provided (solid, 1pt thick)
|
|
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 - Annotation rotation relative to page - R
|
|
if (oMK.dictLookup("R", &oObj)->isInt())
|
|
{
|
|
m_unFlags |= (1 << 6);
|
|
m_unR = oObj.getInt();
|
|
}
|
|
oObj.free();
|
|
|
|
// 7 - Background color - 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 - Default value
|
|
if (oField.dictLookup("DV", &oObj))
|
|
{
|
|
m_sDV = getValue(&oObj);
|
|
if (!m_sDV.empty())
|
|
m_unFlags |= (1 << 8);
|
|
}
|
|
oObj.free();
|
|
|
|
// 17 - Parent - Parent
|
|
m_unRefNumParent = 0;
|
|
if (oField.dictLookupNF("Parent", &oObj)->isRef())
|
|
{
|
|
m_unRefNumParent = oObj.getRefNum() + nStartRefID;
|
|
m_unFlags |= (1 << 17);
|
|
}
|
|
oObj.free();
|
|
|
|
// 18 - Partial field name - 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)
|
|
{
|
|
// Font and font size - from DA
|
|
Ref fontID;
|
|
pField->getFont(&fontID, &m_dFontSize);
|
|
m_unFontStyle = 0;
|
|
|
|
Object oFontRef;
|
|
if (fontID.num < 0)
|
|
{
|
|
if (!GetFontFromAP(pdfDoc, pField, &oFontRef, m_sFontKey))
|
|
{
|
|
oFontRef.free();
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
oFontRef.initRef(fontID.num, fontID.gen);
|
|
|
|
bool bBold = false, bItalic = false;
|
|
GetFontData(pdfDoc, pFontManager, pFontList, &oFontRef, m_sFontName, m_sActualFontName, bBold, bItalic);
|
|
oFontRef.free();
|
|
|
|
// 2 - Actual font
|
|
if (!m_sActualFontName.empty())
|
|
m_unFlags |= (1 << 2);
|
|
|
|
// 4 - Unique font identifier
|
|
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)
|
|
{
|
|
// Incomplete font in pushbutton appearance
|
|
Object oFontRef;
|
|
if (!GetFontFromAP(pdfDoc, pField, &oFontRef, m_sFontKey))
|
|
{
|
|
oFontRef.free();
|
|
return;
|
|
}
|
|
|
|
bool bBold = false, bItalic = false;
|
|
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 - Display as open - Open
|
|
if (oAnnot.dictLookup("Open", &oObj)->isBool() && oObj.getBool())
|
|
m_unFlags |= (1 << 0);
|
|
oObj.free();
|
|
|
|
// 1 - Parent - Parent
|
|
if (oAnnot.dictLookupNF("Parent", &oObj)->isRef())
|
|
{
|
|
m_unFlags |= (1 << 1);
|
|
m_unRefNumParent = oObj.getRefNum() + nStartRefID;
|
|
}
|
|
oObj.free();
|
|
oAnnot.free();
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// Link
|
|
//------------------------------------------------------------------------
|
|
|
|
CAnnotLink::CAnnotLink(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex, int nStartRefID) : CAnnot(pdfDoc, oAnnotRef, nPageIndex, nStartRefID)
|
|
{
|
|
m_unFlags = 0;
|
|
m_pAction = NULL;
|
|
m_pPA = NULL;
|
|
|
|
Object oAnnot, oObj, oObj2;
|
|
XRef* pXref = pdfDoc->getXRef();
|
|
oAnnotRef->fetch(pXref, &oAnnot);
|
|
|
|
// 0 - Action - A
|
|
if (oAnnot.dictLookup("A", &oObj)->isDict())
|
|
{
|
|
m_pAction = getAction(pdfDoc, &oObj);
|
|
if (m_pAction)
|
|
{
|
|
m_unFlags |= (1 << 0);
|
|
m_pAction->sType = "A";
|
|
}
|
|
}
|
|
oObj.free();
|
|
|
|
// 0 - Action from Dest - Dest
|
|
if (!m_pAction && !oAnnot.dictLookup("Dest", &oObj)->isNull())
|
|
{
|
|
m_pAction = getDest(pdfDoc, &oObj);
|
|
if (m_pAction)
|
|
{
|
|
m_unFlags |= (1 << 0);
|
|
m_pAction->sType = "A";
|
|
}
|
|
}
|
|
oObj.free();
|
|
|
|
// 1 - Action - PA
|
|
if (oAnnot.dictLookup("PA", &oObj)->isDict())
|
|
{
|
|
m_pPA = getAction(pdfDoc, &oObj);
|
|
if (m_pPA)
|
|
{
|
|
m_unFlags |= (1 << 1);
|
|
m_pPA->sType = "A";
|
|
}
|
|
}
|
|
oObj.free();
|
|
|
|
// 2 - Highlighting mode - H
|
|
if (oAnnot.dictLookup("H", &oObj)->isName())
|
|
{
|
|
m_unFlags |= (1 << 2);
|
|
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();
|
|
|
|
// 3 - Coordinates - QuadPoints
|
|
if (oAnnot.dictLookup("QuadPoints", &oObj)->isArray())
|
|
{
|
|
m_unFlags |= (1 << 3);
|
|
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();
|
|
|
|
oAnnot.free();
|
|
}
|
|
CAnnotLink::~CAnnotLink()
|
|
{
|
|
RELEASEOBJECT(m_pAction);
|
|
RELEASEOBJECT(m_pPA);
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// 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 - Display as open - Open
|
|
if (oAnnot.dictLookup("Open", &oObj)->isBool() && oObj.getBool())
|
|
m_unFlags |= (1 << 15);
|
|
oObj.free();
|
|
|
|
// 16 - Icon - 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 - State model - 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 - 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();
|
|
|
|
// Text annotation with IRT is not displayed
|
|
if (m_unFlags & (1 << 5))
|
|
m_unAFlags &= ~(1 << 6);
|
|
|
|
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);
|
|
|
|
// Path - 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);
|
|
|
|
// Line coordinates - 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 - Line ending styles - 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 - Line endings color - 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 - Leader lines length - LL
|
|
if (oAnnot.dictLookup("LL", &oObj)->isNum())
|
|
{
|
|
m_unFlags |= (1 << 17);
|
|
m_dLL = oObj.getNum();
|
|
}
|
|
oObj.free();
|
|
|
|
// 18 - Leader line extensions - LLE
|
|
if (oAnnot.dictLookup("LLE", &oObj)->isNum())
|
|
{
|
|
m_unFlags |= (1 << 18);
|
|
m_dLLE = oObj.getNum();
|
|
}
|
|
oObj.free();
|
|
|
|
// 19 - Caption location - Cap
|
|
if (oAnnot.dictLookup("Cap", &oObj)->isBool())
|
|
m_unFlags |= (1 << 19);
|
|
oObj.free();
|
|
|
|
// 20 - Annotation intent - 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 - Leader line offset length - LLO
|
|
if (oAnnot.dictLookup("LLO", &oObj)->isNum())
|
|
{
|
|
m_unFlags |= (1 << 21);
|
|
m_dLLO = oObj.getNum();
|
|
}
|
|
oObj.free();
|
|
|
|
// 22 - Annotation caption position - 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 - Caption text offset - 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);
|
|
|
|
// Coordinates - 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 - 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 - 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 - Differences between Rect and actual size - 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 - Fill color - 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 - 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;
|
|
|
|
// Vertex coordinates - 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 - Line ending styles - 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 - Fill color - 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 - Annotation intent - 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);
|
|
|
|
// Text alignment - 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 - Differences between Rect and actual size - 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 - Callout coordinates - 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 - Default style string - DS
|
|
m_sDS = DictLookupString(&oAnnot, "DS", 17);
|
|
|
|
// 18 - Line ending styles - LE
|
|
if (oAnnot.dictLookup("LE", &oObj)->isName())
|
|
{
|
|
m_unFlags |= (1 << 18);
|
|
m_nLE = getLE(&oObj);
|
|
}
|
|
oObj.free();
|
|
|
|
// 20 - Annotation intent - 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 - Border color - 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 - Differences between Rect and actual size - 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 - Associated symbol - 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 - Icon - 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 - File system - FS
|
|
if (oFS.dictLookup("FS", &oObj)->isName())
|
|
{
|
|
m_unFlags |= (1 << 16);
|
|
m_sFS = oObj.getName();
|
|
}
|
|
oObj.free();
|
|
|
|
// 17 - File specification - F
|
|
m_sF = DictLookupString(&oFS, "F", 17);
|
|
|
|
// 18 - File specification - UF
|
|
m_sUF = DictLookupString(&oFS, "UF", 18);
|
|
|
|
// 19 - File specification - DOS
|
|
m_sDOS = DictLookupString(&oFS, "DOS", 19);
|
|
|
|
// 20 - File specification - Mac
|
|
m_sMac = DictLookupString(&oFS, "Mac", 20);
|
|
|
|
// 21 - File specification - Unix
|
|
m_sUnix = DictLookupString(&oFS, "Unix", 21);
|
|
|
|
// 22 - File identifier - 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 - File volatility - V
|
|
if (oFS.dictLookup("V", &oObj)->isBool() && oObj.getBool())
|
|
m_unFlags |= (1 << 23);
|
|
oObj.free();
|
|
|
|
// 24 - Embedded file streams - 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 - Embedded file streams - RF
|
|
if (oFS.dictLookup("RF", &oObj)->isDict())
|
|
m_unFlags |= (1 << 25);
|
|
oObj.free();
|
|
|
|
// 26 - File description - Desc
|
|
m_sDesc = DictLookupString(&oFS, "Desc", 26);
|
|
|
|
// 27 - Collection - 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);
|
|
|
|
// Icon - 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 - Coordinates - 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 - Fill color - 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 in appearance streams
|
|
|
|
// 17 - Overlay text - OverlayText
|
|
m_sOverlayText = DictLookupString(&oAnnot, "OverlayText", 17);
|
|
|
|
// 18 - Repeat text - Repeat
|
|
if (oAnnot.dictLookup("Repeat", &oObj)->isBool() && oObj.getBool())
|
|
m_unFlags |= (1 << 18);
|
|
|
|
// 19 - Text alignment - Q
|
|
m_nQ = 0;
|
|
if (oAnnot.dictLookup("Q", &oObj)->isInt())
|
|
{
|
|
m_unFlags |= (1 << 19);
|
|
m_nQ = oObj.getInt();
|
|
}
|
|
oObj.free();
|
|
|
|
// Replacement of C: 3 - Color - 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 - Font, size, color of replacement text - 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 (!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 = 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();
|
|
|
|
// Calculation order - 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;
|
|
}
|
|
|
|
// Parents
|
|
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 - Flag - 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 annotation - Popup
|
|
if (oAnnot.dictLookupNF("Popup", &oObj)->isRef())
|
|
{
|
|
m_unFlags |= (1 << 0);
|
|
m_unRefNumPopup = oObj.getRefNum() + nStartRefID;
|
|
}
|
|
|
|
// 1 - User text label - T
|
|
m_sT = DictLookupString(&oAnnot, "T", 1);
|
|
|
|
// 2 - Opacity value - CA
|
|
if (oAnnot.dictLookup("CA", &oObj)->isNum())
|
|
{
|
|
m_unFlags |= (1 << 2);
|
|
m_dCA = oObj.getNum();
|
|
}
|
|
oObj.free();
|
|
|
|
// 3 - Rich text - 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 - Creation date - CreationDate
|
|
m_sCreationDate = DictLookupString(&oAnnot, "CreationDate", 4);
|
|
|
|
// 5 - Reference to reply annotation - IRT
|
|
if (oAnnot.dictLookupNF("IRT", &oObj)->isRef())
|
|
{
|
|
m_unFlags |= (1 << 5);
|
|
m_unRefNumIRT = oObj.getRefNum() + nStartRefID;
|
|
}
|
|
oObj.free();
|
|
|
|
// 6 - Reply annotation type - 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 - Brief description - 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)
|
|
{
|
|
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();
|
|
|
|
// Annotation flag - F
|
|
if (pField->fieldLookup("F", &oObj)->isInt())
|
|
m_unAnnotFlag = oObj.getInt();
|
|
oObj.free();
|
|
|
|
// Page number - P
|
|
m_unPage = pField->getPageNum();
|
|
|
|
// Coordinates - 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;
|
|
if (m_pRect[0] > m_pRect[2])
|
|
std::swap(m_pRect[0], m_pRect[2]);
|
|
if (m_pRect[1] > m_pRect[3])
|
|
std::swap(m_pRect[1], m_pRect[3]);
|
|
|
|
// 0 - Unique name - 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 - Alternative text - 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 - Border effects - 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 - Special color for annotation - 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 - Borders and 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 - Last modification date - 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 - Presence/Absence of appearance
|
|
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 form metadata - 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);
|
|
|
|
// Annotation object number
|
|
m_unRefNum = oAnnotRef->getRefNum() + nStartRefID;
|
|
|
|
// Annotation flag - F
|
|
if (oAnnot.dictLookup("F", &oObj)->isInt())
|
|
m_unAnnotFlag = oObj.getInt();
|
|
oObj.free();
|
|
|
|
// Page number - P
|
|
m_unPage = nPageIndex;
|
|
PDFRectangle* pCropBox = pdfDoc->getCatalog()->getPage(m_unPage)->getCropBox();
|
|
m_dHeight = pCropBox->y2;
|
|
m_dX = pCropBox->x1;
|
|
|
|
// Coordinates - 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);
|
|
|
|
if (m_pRect[0] > m_pRect[2])
|
|
std::swap(m_pRect[0], m_pRect[2]);
|
|
if (m_pRect[1] > m_pRect[3])
|
|
std::swap(m_pRect[1], m_pRect[3]);
|
|
}
|
|
oObj.free();
|
|
|
|
// 0 - Unique name - 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 - Alternative text - 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 - Border effects - 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 - Color - 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 - Borders and 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 - Last modification date - 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 - Presence/Absence of appearance
|
|
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 form metadata - 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())
|
|
{
|
|
// Annotation number for matching with AP
|
|
Object oRef;
|
|
pField->getFieldRef(&oRef);
|
|
m_unRefNum = oRef.getRefNum() + nStartRefID;
|
|
oRef.free();
|
|
|
|
// Coordinates - 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;
|
|
|
|
// Drawing on transparent canvas with specified background color
|
|
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());
|
|
|
|
// Create Gfx
|
|
GBool crop = gTrue;
|
|
PDFRectangle box;
|
|
// Rotation not required
|
|
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);
|
|
|
|
// Appearance coordinates
|
|
m_dRx1 = ((m_bIsStamp ? m_dx1S: m_dx1) - m_dCropX) * m_dWScale - 1;
|
|
m_dRy1 = (pdfDoc->getPageCropHeight(nPageIndex) - (m_bIsStamp ? m_dy2S : 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)
|
|
{
|
|
m_dx1S = m_dx1;
|
|
m_dy2S = m_dy2;
|
|
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)
|
|
{
|
|
// Drawing annotation appearances
|
|
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);
|
|
|
|
// Drawing annotation appearances
|
|
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)
|
|
{
|
|
// Calculation order - CO
|
|
oRes.AddInt(m_arrCO.size());
|
|
for (int i = 0; i < m_arrCO.size(); ++i)
|
|
oRes.AddInt(m_arrCO[i]);
|
|
|
|
// Parent 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.AddInt(unKindFlag);
|
|
if (unKindFlag & (1 << 0))
|
|
oRes.AddDouble(pRect[0]);
|
|
if (unKindFlag & (1 << 1))
|
|
oRes.AddDouble(pRect[1]);
|
|
if (unKindFlag & (1 << 2))
|
|
oRes.AddDouble(pRect[2]);
|
|
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 << 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 << 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 CAnnotLink::ToWASM(NSWasm::CData& oRes)
|
|
{
|
|
oRes.WriteBYTE(1); // Link
|
|
|
|
CAnnot::ToWASM(oRes);
|
|
|
|
oRes.AddInt(m_unFlags);
|
|
if (m_unFlags & (1 << 0))
|
|
m_pAction->ToWASM(oRes);
|
|
if (m_unFlags & (1 << 1))
|
|
m_pPA->ToWASM(oRes);
|
|
if (m_unFlags & (1 << 2))
|
|
oRes.WriteBYTE(m_nH);
|
|
if (m_unFlags & (1 << 3))
|
|
{
|
|
oRes.AddInt((unsigned int)m_arrQuadPoints.size());
|
|
for (int i = 0; i < m_arrQuadPoints.size(); ++i)
|
|
oRes.AddDouble(m_arrQuadPoints[i]);
|
|
}
|
|
}
|
|
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;
|
|
};
|
|
|
|
// Memory release must be called from js side
|
|
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);
|
|
}
|
|
}
|
|
}
|