Create FileAttachment annot

This commit is contained in:
Svetlana Kulikova
2023-11-27 18:19:32 +03:00
parent f024c9fb8f
commit d50451739c
4 changed files with 398 additions and 1 deletions

View File

@ -686,6 +686,27 @@ void ReadAnnotAP(BYTE* pWidgetsAP, int& i)
std::cout << std::endl;
}
void ReadFileAttachment(BYTE* pAnnots, int& i, int n)
{
std::cout << "EF FileAttachment" << n << ".txt, ";
int nFileLength = READ_INT(pAnnots + i);
i += 4;
unsigned long long npFile1 = READ_INT(pAnnots + i);
i += 4;
unsigned long long npFile2 = READ_INT(pAnnots + i);
i += 4;
BYTE* res = (BYTE*)(npFile2 << 32 | npFile1);
NSFile::CFileBinary oFile;
if (oFile.CreateFileW(NSFile::GetProcessDirectory() + L"/FileAttachment" + std::to_wstring(n) + L".txt"))
oFile.WriteFile(res, nFileLength);
oFile.CloseFile();
RELEASEARRAYOBJECTS(res);
}
#include "../../../../../fontengine/ApplicationFontsWorker.h"
#include "../../../../../common/Directory.h"
@ -1443,6 +1464,97 @@ int main(int argc, char* argv[])
std::cout << "Sy " << arrSy[nPathLength] << ", ";
}
}
else if (sType == "FileAttachment")
{
if (nFlags & (1 << 15))
{
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "Name " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
i += nPathLength;
}
if (nFlags & (1 << 16))
{
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "FS " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
i += nPathLength;
}
if (nFlags & (1 << 17))
{
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "F " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
i += nPathLength;
}
if (nFlags & (1 << 18))
{
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "UF " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
i += nPathLength;
}
if (nFlags & (1 << 19))
{
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "DOS " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
i += nPathLength;
}
if (nFlags & (1 << 20))
{
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "Mac " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
i += nPathLength;
}
if (nFlags & (1 << 21))
{
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "Unix " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
i += nPathLength;
}
if (nFlags & (1 << 22))
{
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "ID " << std::string((char*)(pAnnots + i), nPathLength);
i += nPathLength;
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << " " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
i += nPathLength;
}
if (nFlags & (1 << 23))
std::cout << "V true, ";
else
std::cout << "V false, ";
if (nFlags & (1 << 24))
{
int nFlag = READ_INT(pAnnots + i);
i += 4;
if (nFlag & (1 << 0))
ReadFileAttachment(pAnnots, i, 0);
if (nFlag & (1 << 1))
ReadFileAttachment(pAnnots, i, 1);
if (nFlag & (1 << 2))
ReadFileAttachment(pAnnots, i, 2);
if (nFlag & (1 << 3))
ReadFileAttachment(pAnnots, i, 3);
if (nFlag & (1 << 4))
ReadFileAttachment(pAnnots, i, 4);
}
if (nFlags & (1 << 26))
{
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "Desc " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
i += nPathLength;
}
}
std::cout << std::endl;
}

View File

@ -1635,6 +1635,10 @@ void GetPageAnnots(PDFDoc* pdfDoc, NSWasm::CData& oRes, int nPageIndex)
{
pAnnot = new PdfReader::CAnnotInk(pdfDoc, &oAnnotRef, nPageIndex);
}
else if (sType == "FileAttachment")
{
pAnnot = new PdfReader::CAnnotFileAttachment(pdfDoc, &oAnnotRef, nPageIndex);
}
// else if (sType == "Popup")
// {
// pAnnot = new PdfReader::CAnnotPopup(pdfDoc, &oAnnotRef, nPageIndex);

View File

@ -61,6 +61,15 @@ oObj.free();\
put = oObj2.getNum();\
oObj2.free();\
}
#define WRITE_EF(EF) \
{ \
oRes.AddInt(EF->nLength); \
unsigned long long npSubMatrix = (unsigned long long)EF->pFile; \
unsigned int npSubMatrix1 = npSubMatrix & 0xFFFFFFFF; \
oRes.AddInt(npSubMatrix1); \
oRes.AddInt(npSubMatrix >> 32); \
EF->bFree = false; \
}
TextString* getName(Object* oField)
{
@ -412,6 +421,28 @@ BYTE getLE(Object* oObj)
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* pImage = oObj->getStream();
pImage->reset();
pRes->pFile = new BYTE[pRes->nLength];
BYTE* pBufferPtr = pRes->pFile;
for (int nI = 0; nI < pRes->nLength; ++nI)
*pBufferPtr++ = (BYTE)pImage->getChar();
return pRes;
}
//------------------------------------------------------------------------
// Widget
@ -1409,7 +1440,7 @@ CAnnotCaret::CAnnotCaret(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex) : CM
oAnnotRef->fetch(pXref, &oAnnot);
// 16 - Различия Rect и фактического размера - RD
if (oAnnot.dictLookup("RD", &oObj)->isArray())
if (oAnnot.dictLookup("RD", &oObj)->isArray() && oObj.arrayGetLength() == 4)
{
m_unFlags |= (1 << 15);
ARR_GET_NUM(oObj, 0, m_pRD[0]);
@ -1434,6 +1465,132 @@ CAnnotCaret::CAnnotCaret(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex) : CM
oAnnot.free();
}
//------------------------------------------------------------------------
// FileAttachment
//------------------------------------------------------------------------
CAnnotFileAttachment::CAnnotFileAttachment(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex) : CMarkupAnnot(pdfDoc, oAnnotRef, nPageIndex)
{
m_pEF = NULL;
Object oAnnot, oObj, oObj2;
XRef* pXref = pdfDoc->getXRef();
oAnnotRef->fetch(pXref, &oAnnot);
// 16 - Иконка - 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;
}
// 17 - Файловая система - FS
if (oFS.dictLookup("FS", &oObj)->isName())
{
m_unFlags |= (1 << 16);
m_sFS = oObj.getName();
}
oObj.free();
// 18 - Спецификация файла - F
DICT_LOOKUP_STRING(oFS.dictLookup, "F", 17, m_sF);
// 19 - Спецификация файла - UF
DICT_LOOKUP_STRING(oFS.dictLookup, "UF", 18, m_sUF);
// 20 - Спецификация файла - DOS
DICT_LOOKUP_STRING(oFS.dictLookup, "DOS", 19, m_sDOS);
// 21 - Спецификация файла - Mac
DICT_LOOKUP_STRING(oFS.dictLookup, "Mac", 20, m_sMac);
// 22 - Спецификация файла - Unix
DICT_LOOKUP_STRING(oFS.dictLookup, "Unix", 21, m_sUnix);
// 23 - Идентификатор файла - 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();
// 24 - Изменчивость файла - V
if (oFS.dictLookup("V", &oObj)->isBool() && oObj.getBool())
m_unFlags |= (1 << 23);
oObj.free();
// 25 - Встроенные файловые потоки - 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();
// 26 - Встроенные файловые потоки - RF
Object oRF;
if (oFS.dictLookup("RF", &oRF)->isDict())
{
m_unFlags |= (1 << 25);
}
oRF.free();
// 27 - Описание файла - Desc
DICT_LOOKUP_STRING(oFS.dictLookup, "Desc", 26, m_sDesc);
// 28 - Коллекция - Cl
if (oFS.dictLookup("Cl", &oObj)->isDict())
{
m_unFlags |= (1 << 27);
}
oObj.free();
oFS.free(); oAnnot.free();
}
CAnnotFileAttachment::~CAnnotFileAttachment()
{
RELEASEOBJECT(m_pEF);
}
//------------------------------------------------------------------------
// Annots
//------------------------------------------------------------------------
@ -2736,4 +2893,72 @@ void CAnnotCaret::ToWASM(NSWasm::CData& oRes)
if (m_unFlags & (1 << 16))
oRes.WriteBYTE(m_nSy);
}
void CAnnotFileAttachment::ToWASM(NSWasm::CData& oRes)
{
oRes.WriteBYTE(16); // FileAttachment
CMarkupAnnot::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);
// Освобождение памяти необходимо вызвать с js стороны
if (m_pEF->m_pF)
{
nFlag |= (1 << 0);
WRITE_EF(m_pEF->m_pF);
}
if (m_pEF->m_pUF)
{
nFlag |= (1 << 1);
WRITE_EF(m_pEF->m_pUF);
}
if (m_pEF->m_pDOS)
{
nFlag |= (1 << 2);
WRITE_EF(m_pEF->m_pDOS);
}
if (m_pEF->m_pMac)
{
nFlag |= (1 << 3);
WRITE_EF(m_pEF->m_pMac);
}
if (m_pEF->m_pUnix)
{
nFlag |= (1 << 4);
WRITE_EF(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))
{
}
}
}

View File

@ -473,6 +473,62 @@ private:
double m_pRD[4]{}; // Различия Rect и фактического размера
};
//------------------------------------------------------------------------
// PdfReader::CAnnotFileAttachment
//------------------------------------------------------------------------
class CAnnotFileAttachment final : public CMarkupAnnot
{
public:
CAnnotFileAttachment(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex);
virtual ~CAnnotFileAttachment();
void ToWASM(NSWasm::CData& oRes) override;
struct CEmbeddedFile
{
BYTE* pFile;
int nLength;
bool bFree;
CEmbeddedFile() : pFile(NULL), nLength(0), bFree(true) {}
~CEmbeddedFile() { if (bFree) RELEASEARRAYOBJECTS(pFile); }
};
struct CEmbeddedFiles
{
CEmbeddedFile* m_pF;
CEmbeddedFile* m_pUF;
CEmbeddedFile* m_pDOS;
CEmbeddedFile* m_pMac;
CEmbeddedFile* m_pUnix;
CEmbeddedFiles() : m_pF(NULL), m_pUF(NULL), m_pDOS(NULL), m_pMac(NULL), m_pUnix(NULL) {}
~CEmbeddedFiles()
{
RELEASEOBJECT(m_pF);
RELEASEOBJECT(m_pUF);
RELEASEOBJECT(m_pDOS);
RELEASEOBJECT(m_pMac);
RELEASEOBJECT(m_pUnix);
}
};
private:
std::string m_sName; // Иконка
std::string m_sFS; // Файловая система
std::string m_sDesc; // Описание файла
std::string m_sF; // Спецификация файла (обратная совместимость)
std::string m_sUF; // Спецификация файла (кросс-платформенная и межъязыковая совместимость)
std::string m_sDOS; // Спецификация файла DOS
std::string m_sMac; // Спецификация файла Mac
std::string m_sUnix; // Спецификация файла Unix
std::pair<std::string, std::string> m_sID; // Идентификатор файла
CEmbeddedFiles* m_pEF; // EF содержит F/UF/DOS/Mac/Unix со ссылками на встроенные файловые потоки по соответствующим спецификациях
// TODO RF содержит F/UF/DOS/Mac/Unix с массивами связанных файлов по соответствующим спецификациях
// TODO Cl коллекция для создания пользовательского интерфейса
};
//------------------------------------------------------------------------
// PdfReader::CAnnots
//------------------------------------------------------------------------