Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Unified Diff: core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp

Issue 1366593002: Support linearized loading (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
index 7482f0b8e4fc12427b49cdc9752ad5003771310a..7f8ae544112088691fde3c2128f149033e3f1af8 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
@@ -13,6 +13,7 @@
#include "../../../include/fpdfapi/fpdf_parser.h"
#include "../../../include/fxcrt/fx_safe_types.h"
#include "../fpdf_page/pageint.h"
+#include "parser_int.h"
FX_BOOL IsSignatureDict(const CPDF_Dictionary* pDict) {
CPDF_Object* pType = pDict->GetElementValue(FX_BSTRC("Type"));
@@ -2811,7 +2812,9 @@ void CPDF_SyntaxParser::GetBinary(uint8_t* buffer, FX_DWORD size) {
class CPDF_DataAvail final : public IPDF_DataAvail {
public:
- CPDF_DataAvail(IFX_FileAvail* pFileAvail, IFX_FileRead* pFileRead);
+ CPDF_DataAvail(IFX_FileAvail* pFileAvail,
+ IFX_FileRead* pFileRead,
+ FX_BOOL bSupportHintTable);
~CPDF_DataAvail() override;
virtual FX_BOOL IsDocAvail(IFX_DownloadHints* pHints) override;
@@ -2828,6 +2831,10 @@ class CPDF_DataAvail final : public IPDF_DataAvail {
virtual void GetLinearizedMainXRefInfo(FX_FILESIZE* pPos,
FX_DWORD* pSize) override;
+ int GetPageCount() const;
+ CPDF_Dictionary* GetPage(int index);
+
+ friend class CPDF_HintTables;
protected:
static const int kMaxDataAvailRecursionDepth = 64;
@@ -2841,6 +2848,7 @@ class CPDF_DataAvail final : public IPDF_DataAvail {
FX_BOOL CheckDocStatus(IFX_DownloadHints* pHints);
FX_BOOL CheckHeader(IFX_DownloadHints* pHints);
FX_BOOL CheckFirstPage(IFX_DownloadHints* pHints);
+ FX_BOOL CheckHintTables(IFX_DownloadHints* pHints);
FX_BOOL CheckEnd(IFX_DownloadHints* pHints);
FX_BOOL CheckCrossRef(IFX_DownloadHints* pHints);
FX_BOOL CheckCrossRefItem(IFX_DownloadHints* pHints);
@@ -2863,7 +2871,9 @@ class CPDF_DataAvail final : public IPDF_DataAvail {
void SetStartOffset(FX_FILESIZE dwOffset);
FX_BOOL GetNextToken(CFX_ByteString& token);
FX_BOOL GetNextChar(uint8_t& ch);
- CPDF_Object* ParseIndirectObjectAt(FX_FILESIZE pos, FX_DWORD objnum);
+ CPDF_Object* ParseIndirectObjectAt(FX_FILESIZE pos,
+ FX_DWORD objnum,
+ CPDF_IndirectObjects* pObjList = NULL);
CPDF_Object* GetObject(FX_DWORD objnum,
IFX_DownloadHints* pHints,
FX_BOOL* pExistInFile);
@@ -2894,6 +2904,9 @@ class CPDF_DataAvail final : public IPDF_DataAvail {
FX_BOOL CheckPageCount(IFX_DownloadHints* pHints);
FX_BOOL IsFirstCheck(int iPage);
void ResetFirstCheck(int iPage);
+ FX_BOOL IsDataAvail(FX_FILESIZE offset,
+ FX_DWORD size,
+ IFX_DownloadHints* pHints);
CPDF_Parser m_parser;
@@ -3007,6 +3020,9 @@ class CPDF_DataAvail final : public IPDF_DataAvail {
std::set<FX_DWORD> m_pageMapCheckState;
std::set<FX_DWORD> m_pagesLoadState;
+
+ nonstd::unique_ptr<CPDF_HintTables> m_pHintTables;
+ FX_BOOL m_bSupportHintTable;
};
IPDF_DataAvail::IPDF_DataAvail(IFX_FileAvail* pFileAvail,
@@ -3016,14 +3032,15 @@ IPDF_DataAvail::IPDF_DataAvail(IFX_FileAvail* pFileAvail,
// static
IPDF_DataAvail* IPDF_DataAvail::Create(IFX_FileAvail* pFileAvail,
IFX_FileRead* pFileRead) {
- return new CPDF_DataAvail(pFileAvail, pFileRead);
+ return new CPDF_DataAvail(pFileAvail, pFileRead, FALSE);
}
// static
int CPDF_DataAvail::s_CurrentDataAvailRecursionDepth = 0;
CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail,
- IFX_FileRead* pFileRead)
+ IFX_FileRead* pFileRead,
+ FX_BOOL bSupportHintTable)
: IPDF_DataAvail(pFileAvail, pFileRead) {
m_Pos = 0;
m_dwFileLen = 0;
@@ -3069,6 +3086,7 @@ CPDF_DataAvail::CPDF_DataAvail(IFX_FileAvail* pFileAvail,
m_bTotalLoadPageTree = FALSE;
m_bCurPageDictLoadOK = FALSE;
m_bLinearedDataOK = FALSE;
+ m_bSupportHintTable = bSupportHintTable;
}
CPDF_DataAvail::~CPDF_DataAvail() {
if (m_pLinearized) {
@@ -3080,9 +3098,9 @@ CPDF_DataAvail::~CPDF_DataAvail() {
if (m_pTrailer) {
m_pTrailer->Release();
}
- int32_t i = 0;
+
int32_t iSize = m_arrayAcroforms.GetSize();
- for (i = 0; i < iSize; ++i) {
+ for (int i = 0; i < iSize; ++i) {
((CPDF_Object*)m_arrayAcroforms.GetAt(i))->Release();
}
}
@@ -3164,28 +3182,11 @@ FX_BOOL CPDF_DataAvail::IsObjectsAvail(CFX_PtrArray& obj_array,
CPDF_Reference* pRef = (CPDF_Reference*)pObj;
FX_DWORD dwNum = pRef->GetRefObjNum();
FX_FILESIZE offset;
- FX_DWORD original_size = GetObjectSize(dwNum, offset);
- pdfium::base::CheckedNumeric<FX_DWORD> size = original_size;
- if (size.ValueOrDefault(0) == 0 || offset < 0 ||
- offset >= m_dwFileLen) {
- break;
- }
-
- size += offset;
- size += 512;
- if (!size.IsValid()) {
- break;
- }
- if (size.ValueOrDie() > m_dwFileLen) {
- size = m_dwFileLen - offset;
- } else {
- size = original_size + 512;
- }
- if (!size.IsValid()) {
+ FX_DWORD size = GetObjectSize(dwNum, offset);
+ if (size == 0 || offset < 0 || offset >= m_dwFileLen) {
break;
}
- if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) {
- pHints->AddSegment(offset, size.ValueOrDie());
+ if (!IsDataAvail(offset, size, pHints)) {
ret_array.Add(pObj);
count++;
} else if (!m_objnum_array.Find(dwNum)) {
@@ -3285,6 +3286,8 @@ FX_BOOL CPDF_DataAvail::CheckDocStatus(IFX_DownloadHints* pHints) {
case PDF_DATAAVAIL_FIRSTPAGE:
case PDF_DATAAVAIL_FIRSTPAGE_PREPARE:
return CheckFirstPage(pHints);
+ case PDF_DATAAVAIL_HINTTABLE:
+ return CheckHintTables(pHints);
case PDF_DATAAVAIL_END:
return CheckEnd(pHints);
case PDF_DATAAVAIL_CROSSREF:
@@ -3369,53 +3372,24 @@ FX_BOOL CPDF_DataAvail::LoadAllXref(IFX_DownloadHints* pHints) {
CPDF_Object* CPDF_DataAvail::GetObject(FX_DWORD objnum,
IFX_DownloadHints* pHints,
FX_BOOL* pExistInFile) {
- CPDF_Object* pRet = NULL;
- FX_DWORD original_size = 0;
+ CPDF_Object* pRet = nullptr;
+ FX_DWORD size = 0;
FX_FILESIZE offset = 0;
- CPDF_Parser* pParser = NULL;
-
- if (pExistInFile) {
+ CPDF_Parser* pParser = nullptr;
+ if (pExistInFile)
*pExistInFile = TRUE;
- }
if (m_pDocument == NULL) {
- original_size = (FX_DWORD)m_parser.GetObjectSize(objnum);
+ size = (FX_DWORD)m_parser.GetObjectSize(objnum);
offset = m_parser.GetObjectOffset(objnum);
pParser = &m_parser;
} else {
- original_size = GetObjectSize(objnum, offset);
+ size = GetObjectSize(objnum, offset);
pParser = (CPDF_Parser*)(m_pDocument->GetParser());
}
-
- pdfium::base::CheckedNumeric<FX_DWORD> size = original_size;
- if (size.ValueOrDefault(0) == 0 || offset < 0 || offset >= m_dwFileLen) {
- if (pExistInFile)
- *pExistInFile = FALSE;
-
- return NULL;
- }
-
- size += offset;
- size += 512;
- if (!size.IsValid()) {
- return NULL;
- }
-
- if (size.ValueOrDie() > m_dwFileLen) {
- size = m_dwFileLen - offset;
- } else {
- size = original_size + 512;
- }
-
- if (!size.IsValid()) {
- return NULL;
- }
-
- if (!m_pFileAvail->IsDataAvail(offset, size.ValueOrDie())) {
- pHints->AddSegment(offset, size.ValueOrDie());
- return NULL;
+ if (!IsDataAvail(offset, size, pHints)) {
+ return nullptr;
}
-
if (pParser) {
pRet = pParser->ParseIndirectObject(NULL, objnum, NULL);
}
@@ -3716,15 +3690,81 @@ FX_BOOL CPDF_DataAvail::CheckFirstPage(IFX_DownloadHints* pHints) {
} else {
m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
}
- if (!bNeedDownLoad && m_docStatus == PDF_DATAAVAIL_FIRSTPAGE_PREPARE) {
+ if (bNeedDownLoad || m_docStatus != PDF_DATAAVAIL_FIRSTPAGE_PREPARE) {
+ m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
+ return FALSE;
+ }
+ m_docStatus =
+ m_bSupportHintTable ? PDF_DATAAVAIL_HINTTABLE : PDF_DATAAVAIL_DONE;
+ return TRUE;
+}
+FX_BOOL CPDF_DataAvail::IsDataAvail(FX_FILESIZE offset,
+ FX_DWORD size,
+ IFX_DownloadHints* pHints) {
+ if (!pHints || offset > m_dwFileLen)
+ return TRUE;
+ FX_SAFE_DWORD safeSize = pdfium::base::checked_cast<FX_DWORD>(offset);
+ safeSize += size;
+ safeSize += 512;
+ if (!safeSize.IsValid() || safeSize.ValueOrDie() > m_dwFileLen)
+ size = m_dwFileLen - offset;
+ else
+ size += 512;
+ if (!m_pFileAvail->IsDataAvail(offset, size)) {
+ pHints->AddSegment(offset, size);
+ return FALSE;
+ }
+ return TRUE;
+}
+FX_BOOL CPDF_DataAvail::CheckHintTables(IFX_DownloadHints* pHints) {
+ CPDF_Dictionary* pDict = m_pLinearized->GetDict();
+ if (!pDict || !pHints) {
+ return TRUE;
+ }
+ if (!pDict->KeyExist(FX_BSTRC("H")) || !pDict->KeyExist(FX_BSTRC("O")) ||
+ !pDict->KeyExist(FX_BSTRC("N"))) {
m_docStatus = PDF_DATAAVAIL_DONE;
return TRUE;
}
- m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE;
- return FALSE;
+ int nPageCount = pDict->GetElementValue(FX_BSTRC("N"))->GetInteger();
+ if (nPageCount <= 1) {
+ m_docStatus = PDF_DATAAVAIL_DONE;
+ return TRUE;
+ }
+ CPDF_Array* pHintStreamRange = pDict->GetArray(FX_BSTRC("H"));
+ FX_FILESIZE szHSStart =
+ pHintStreamRange->GetElementValue(0)
+ ? pHintStreamRange->GetElementValue(0)->GetInteger()
+ : 0;
+ FX_FILESIZE szHSLength =
+ pHintStreamRange->GetElementValue(1)
+ ? pHintStreamRange->GetElementValue(1)->GetInteger()
+ : 0;
+ if (szHSStart < 0 || szHSLength <= 0) {
+ m_docStatus = PDF_DATAAVAIL_DONE;
+ return TRUE;
+ }
+ if (!IsDataAvail(szHSStart, szHSLength, pHints)) {
+ return FALSE;
+ }
+ m_syntaxParser.InitParser(m_pFileRead, m_dwHeaderOffset);
+ nonstd::unique_ptr<CPDF_HintTables> pHintTables(
+ new CPDF_HintTables(this, pDict));
+ CPDF_Stream* pHintStream = (CPDF_Stream*)ParseIndirectObjectAt(szHSStart, 0);
+ if (!pHintStream || pHintStream->GetType() != PDFOBJ_STREAM) {
+ return FALSE;
+ }
+ if (pHintTables && !pHintTables->LoadHintStream(pHintStream)) {
+ return FALSE;
+ }
+ m_pHintTables.reset(pHintTables.release());
+ m_docStatus = PDF_DATAAVAIL_DONE;
+ return TRUE;
}
-CPDF_Object* CPDF_DataAvail::ParseIndirectObjectAt(FX_FILESIZE pos,
- FX_DWORD objnum) {
+CPDF_Object* CPDF_DataAvail::ParseIndirectObjectAt(
+ FX_FILESIZE pos,
+ FX_DWORD objnum,
+ CPDF_IndirectObjects* pObjList) {
FX_FILESIZE SavedPos = m_syntaxParser.SavePos();
m_syntaxParser.RestorePos(pos);
FX_BOOL bIsNumber;
@@ -3745,28 +3785,29 @@ CPDF_Object* CPDF_DataAvail::ParseIndirectObjectAt(FX_FILESIZE pos,
m_syntaxParser.RestorePos(SavedPos);
return NULL;
}
- CPDF_Object* pObj = m_syntaxParser.GetObject(NULL, objnum, gennum, 0);
+ CPDF_Object* pObj =
+ m_syntaxParser.GetObject(pObjList, parser_objnum, gennum, 0);
m_syntaxParser.RestorePos(SavedPos);
return pObj;
}
int32_t CPDF_DataAvail::IsLinearizedPDF() {
FX_DWORD req_size = 1024;
if (!m_pFileAvail->IsDataAvail(0, req_size)) {
- return PDF_UNKNOW_LINEARIZED;
+ return PDF_FILE_UNKNOW;
}
if (!m_pFileRead) {
- return PDF_NOT_LINEARIZED;
+ return PDF_FILE_NOTLINEARIZED;
}
FX_FILESIZE dwSize = m_pFileRead->GetSize();
if (dwSize < (FX_FILESIZE)req_size) {
- return PDF_UNKNOW_LINEARIZED;
+ return PDF_FILE_UNKNOW;
}
uint8_t buffer[1024];
m_pFileRead->ReadBlock(buffer, 0, req_size);
if (IsLinearizedFile(buffer, req_size)) {
- return PDF_IS_LINEARIZED;
+ return PDF_FILE_LINEARIZED;
}
- return PDF_NOT_LINEARIZED;
+ return PDF_FILE_NOTLINEARIZED;
}
FX_BOOL CPDF_DataAvail::IsLinearizedFile(uint8_t* pData, FX_DWORD dwLen) {
CFX_SmartPointer<IFX_FileStream> file(
@@ -4503,6 +4544,12 @@ FX_BOOL CPDF_DataAvail::IsPageAvail(int32_t iPage, IFX_DownloadHints* pHints) {
if (!CheckLinearizedData(pHints)) {
return FALSE;
}
+ if (m_pHintTables) {
+ if (!m_pHintTables->CheckPage(iPage, pHints))
+ return FALSE;
+ m_pagesLoadState.insert(iPage);
+ return TRUE;
+ }
if (m_bMainXRefLoadedOK) {
if (m_bTotalLoadPageTree) {
if (!LoadPages(pHints)) {
@@ -4623,6 +4670,45 @@ void CPDF_DataAvail::GetLinearizedMainXRefInfo(FX_FILESIZE* pPos,
*pSize = (FX_DWORD)(m_dwFileLen - m_dwLastXRefOffset);
}
}
+int CPDF_DataAvail::GetPageCount() const {
+ if (!m_pDocument && !m_pLinearized) {
+ return 0;
+ }
+ if (m_pLinearized) {
+ CPDF_Dictionary* pDict = m_pLinearized->GetDict();
+ CPDF_Object* pObj = pDict ? pDict->GetElementValue(FX_BSTRC("N")) : nullptr;
+ return pObj ? pObj->GetInteger() : 0;
+ }
+ return m_pDocument->GetPageCount();
+}
+CPDF_Dictionary* CPDF_DataAvail::GetPage(int index) {
+ if (!m_pDocument || index < 0 || index >= this->GetPageCount()) {
+ return nullptr;
+ }
+ if (m_pLinearized) {
+ CPDF_Dictionary* pDict = m_pLinearized->GetDict();
+ CPDF_Object* pObj = pDict ? pDict->GetElementValue(FX_BSTRC("P")) : nullptr;
+ int pageNum = pObj ? pObj->GetInteger() : 0;
+ if (m_pHintTables && index != pageNum) {
+ FX_FILESIZE szPageStartPos = 0;
+ FX_FILESIZE szPageLength = 0;
+ FX_DWORD dwObjNum = 0;
+ FX_BOOL bPagePosGot = m_pHintTables->GetPagePos(index, szPageStartPos,
+ szPageLength, dwObjNum);
+ if (!bPagePosGot) {
+ return nullptr;
+ }
+ m_syntaxParser.InitParser(m_pFileRead, (FX_DWORD)szPageStartPos);
+ CPDF_Object* pPageDict = ParseIndirectObjectAt(0, dwObjNum, m_pDocument);
+ if (!pPageDict) {
+ return nullptr;
+ }
+ m_pDocument->InsertIndirectObject(dwObjNum, pPageDict);
+ return pPageDict->GetDict();
+ }
+ }
+ return m_pDocument->GetPage(index);
+}
int32_t CPDF_DataAvail::IsFormAvail(IFX_DownloadHints* pHints) {
if (!m_pDocument) {
return PDFFORM_AVAIL;
@@ -4690,3 +4776,333 @@ CPDF_PageNode::~CPDF_PageNode() {
}
m_childNode.RemoveAll();
}
+CPDF_HintTables::~CPDF_HintTables() {
+ m_nFirstPageSharedObjs = 0;
+ m_szFirstPageObjOffset = 0;
+ m_dwDeltaNObjsArray.RemoveAll();
+ m_dwNSharedObjsArray.RemoveAll();
+ m_dwSharedObjNumArray.RemoveAll();
+ m_dwIdentifierArray.RemoveAll();
+ m_szPageOffsetArray.RemoveAll();
+ m_szSharedObjOffsetArray.RemoveAll();
+}
+FX_DWORD CPDF_HintTables::GetItemLength(int index,
+ const CFX_FileSizeArray& szArray) {
+ if (index < 0 || index > szArray.GetSize() - 2)
+ return 0;
+ return szArray[index + 1] - szArray[index];
+}
+FX_BOOL CPDF_HintTables::ReadPageHintTable(CFX_BitStream* hStream) {
+ if (!hStream)
+ return FALSE;
+ int nStreamOffset = ReadPrimaryHintStreamOffset();
+ int nStreamLen = ReadPrimaryHintStreamLength();
+ if (nStreamOffset < 0 || nStreamLen < 1)
+ return FALSE;
+ // Item 1: The least number of objects in a page.
+ FX_DWORD dwObjLeastNum = hStream->GetBits(32);
+ // Item 2: The location of the first page's page object.
+ FX_DWORD dwFirstObjLoc = hStream->GetBits(32);
+ if (dwFirstObjLoc > nStreamOffset) {
+ FX_SAFE_DWORD safeLoc = pdfium::base::checked_cast<FX_DWORD>(nStreamLen);
+ safeLoc += dwFirstObjLoc;
+ if (!safeLoc.IsValid())
+ return FALSE;
+ m_szFirstPageObjOffset =
+ pdfium::base::checked_cast<FX_FILESIZE>(safeLoc.ValueOrDie());
+ } else {
+ m_szFirstPageObjOffset =
+ pdfium::base::checked_cast<FX_FILESIZE>(dwFirstObjLoc);
+ }
+ // Item 3: The number of bits needed to represent the difference
+ // between the greatest and least number of objects in a page.
+ FX_DWORD dwDeltaObjectsBits = hStream->GetBits(16);
+ // Item 4: The least length of a page in bytes.
+ FX_DWORD dwPageLeastLen = hStream->GetBits(32);
+ // Item 5: The number of bits needed to represent the difference
+ // between the greatest and least length of a page, in bytes.
+ FX_DWORD dwDeltaPageLenBits = hStream->GetBits(16);
+ // Skip Item 6, 7, 8, 9 total 96 bits.
+ hStream->SkipBits(96);
+ // Item 10: The number of bits needed to represent the greatest
+ // number of shared object references.
+ FX_DWORD dwSharedObjBits = hStream->GetBits(16);
+ // Item 11: The number of bits needed to represent the numerically
+ // greatest shared object identifier used by the pages.
+ FX_DWORD dwSharedIdBits = hStream->GetBits(16);
+ // Item 12: The number of bits needed to represent the numerator of
+ // the fractional position for each shared object reference. For each
+ // shared object referenced from a page, there is an indication of
+ // where in the page's content stream the object is first referenced.
+ FX_DWORD dwSharedNumeratorBits = hStream->GetBits(16);
+ // Item 13: Skip Item 13 which has 16 bits.
+ FX_DWORD dwSharedDenominator = hStream->GetBits(16);
+ CPDF_Object* pPageNum = m_pLinearizedDict->GetElementValue(FX_BSTRC("N"));
+ int nPages = pPageNum ? pPageNum->GetInteger() : 0;
+ if (nPages < 1)
+ return FALSE;
+ for (int i = 0; i < nPages; ++i) {
+ FX_SAFE_DWORD safeDeltaObj = hStream->GetBits(dwDeltaObjectsBits);
+ safeDeltaObj += dwObjLeastNum;
+ if (!safeDeltaObj.IsValid())
+ return FALSE;
+ m_dwDeltaNObjsArray.Add(safeDeltaObj.ValueOrDie());
+ }
+ hStream->ByteAlign();
+ CFX_DWordArray dwPageLenArray;
+ for (int i = 0; i < nPages; ++i) {
+ FX_SAFE_DWORD safePageLen = hStream->GetBits(dwDeltaPageLenBits);
+ safePageLen += dwPageLeastLen;
+ if (!safePageLen.IsValid())
+ return FALSE;
+ dwPageLenArray.Add(safePageLen.ValueOrDie());
+ }
+ CPDF_Object* pOffsetE = m_pLinearizedDict->GetElementValue(FX_BSTRC("E"));
+ int nOffsetE = pOffsetE ? pOffsetE->GetInteger() : -1;
+ if (nOffsetE < 0)
+ return FALSE;
+ CPDF_Object* pFirstPageNum =
+ m_pLinearizedDict->GetElementValue(FX_BSTRC("P"));
+ int nFirstPageNum = pFirstPageNum ? pFirstPageNum->GetInteger() : 0;
+ for (int i = 0; i < nPages; ++i) {
+ if (i == nFirstPageNum) {
+ m_szPageOffsetArray.Add(m_szFirstPageObjOffset);
+ } else if (i == nFirstPageNum + 1) {
+ if (i == 1) {
+ m_szPageOffsetArray.Add(nOffsetE);
+ } else {
+ m_szPageOffsetArray.Add(m_szPageOffsetArray[i - 2] +
+ dwPageLenArray[i - 2]);
+ }
+ } else {
+ if (i == 0) {
+ m_szPageOffsetArray.Add(nOffsetE);
+ } else {
+ m_szPageOffsetArray.Add(m_szPageOffsetArray[i - 1] +
+ dwPageLenArray[i - 1]);
+ }
+ }
+ }
+ if (nPages > 0) {
+ m_szPageOffsetArray.Add(m_szPageOffsetArray[nPages - 1] +
+ dwPageLenArray[nPages - 1]);
+ }
+ hStream->ByteAlign();
+ // number of shared objects
+ for (int i = 0; i < nPages; i++) {
+ m_dwNSharedObjsArray.Add(hStream->GetBits(dwSharedObjBits));
+ }
+ hStream->ByteAlign();
+ // array of identifier, sizes = nshared_objects
+ for (int i = 0; i < nPages; i++) {
+ for (int j = 0; j < m_dwNSharedObjsArray[i]; j++) {
+ m_dwIdentifierArray.Add(hStream->GetBits(dwSharedIdBits));
+ }
+ }
+ hStream->ByteAlign();
+ for (int i = 0; i < nPages; i++) {
+ FX_SAFE_DWORD safeSize = m_dwNSharedObjsArray[i];
+ safeSize *= dwSharedNumeratorBits;
+ if (!safeSize.IsValid())
+ return FALSE;
+ hStream->SkipBits(safeSize.ValueOrDie());
+ }
+ hStream->ByteAlign();
+ FX_SAFE_DWORD safeTotalPageLen = pdfium::base::checked_cast<FX_DWORD>(nPages);
+ safeTotalPageLen *= dwDeltaPageLenBits;
+ if (!safeTotalPageLen.IsValid())
+ return FALSE;
+ hStream->SkipBits(safeTotalPageLen.ValueOrDie());
+ hStream->ByteAlign();
+ return TRUE;
+}
+FX_BOOL CPDF_HintTables::ReadSharedObjHintTable(CFX_BitStream* hStream) {
+ if (!hStream)
+ return FALSE;
+ int nStreamOffset = ReadPrimaryHintStreamOffset();
+ int nStreamLen = ReadPrimaryHintStreamLength();
+ if (nStreamOffset < 0 || nStreamLen < 1)
+ return FALSE;
+ // Item 1: The object number of the first object in the shared objects
+ // section.
+ FX_DWORD dwFirstSharedObjNum = hStream->GetBits(32);
+ // Item 2: The location of the first object in the shared objects section.
+ FX_DWORD dwFirstSharedObjLoc = hStream->GetBits(32);
+ if (dwFirstSharedObjLoc > nStreamOffset)
+ dwFirstSharedObjLoc += nStreamLen;
+ // Item 3: The number of shared object entries for the first page.
+ m_nFirstPageSharedObjs = hStream->GetBits(32);
+ // Item 4: The number of shared object entries for the shared objects
+ // section, including the number of shared object entries for the first page.
+ FX_DWORD dwSharedObjTotal = hStream->GetBits(32);
+ // Item 5: The number of bits needed to represent the greatest number of
+ // objects in a shared object group. Skipped.
+ hStream->SkipBits(16);
+ // Item 6: The least length of a shared object group in bytes.
+ FX_DWORD dwGroupLeastLen = hStream->GetBits(32);
+ // Item 7: The number of bits needed to represent the difference between the
+ // greatest and least length of a shared object group, in bytes.
+ FX_DWORD dwDeltaGroupLen = hStream->GetBits(16);
+ CPDF_Object* pFirstPageObj =
+ m_pLinearizedDict->GetElementValue(FX_BSTRC("O"));
+ int nFirstPageObjNum = pFirstPageObj ? pFirstPageObj->GetInteger() : -1;
+ if (nFirstPageObjNum < 0)
+ return FALSE;
+ FX_DWORD dwPrevObjLen = 0;
+ FX_DWORD dwCurObjLen = 0;
+ for (int i = 0; i < dwSharedObjTotal; ++i) {
+ dwPrevObjLen = dwCurObjLen;
+ FX_SAFE_DWORD safeObjLen = hStream->GetBits(dwDeltaGroupLen);
+ safeObjLen += dwGroupLeastLen;
+ if (!safeObjLen.IsValid())
+ return FALSE;
+ dwCurObjLen = safeObjLen.ValueOrDie();
+ if (i < m_nFirstPageSharedObjs) {
+ m_dwSharedObjNumArray.Add(nFirstPageObjNum + i);
+ if (i == 0)
+ m_szSharedObjOffsetArray.Add(m_szFirstPageObjOffset);
+ } else {
+ FX_SAFE_DWORD safeObjNum = dwFirstSharedObjNum;
+ safeObjNum += i - m_nFirstPageSharedObjs;
+ if (safeObjNum.IsValid())
+ return FALSE;
+ m_dwSharedObjNumArray.Add(safeObjNum.ValueOrDie());
+ if (i == m_nFirstPageSharedObjs)
+ m_szSharedObjOffsetArray.Add(
+ pdfium::base::checked_cast<int32_t>(dwFirstSharedObjLoc));
+ }
+ if (i != 0 && i != m_nFirstPageSharedObjs) {
+ FX_SAFE_INT32 safeLoc = pdfium::base::checked_cast<int32_t>(dwPrevObjLen);
+ safeLoc += m_szSharedObjOffsetArray[i - 1];
+ if (!safeLoc.IsValid())
+ return FALSE;
+ m_szSharedObjOffsetArray.Add(safeLoc.ValueOrDie());
+ }
+ }
+ if (dwSharedObjTotal > 0) {
+ FX_SAFE_INT32 safeLoc = pdfium::base::checked_cast<int32_t>(dwCurObjLen);
+ safeLoc += m_szSharedObjOffsetArray[dwSharedObjTotal - 1];
+ if (!safeLoc.IsValid())
+ return FALSE;
+ m_szSharedObjOffsetArray.Add(safeLoc.ValueOrDie());
+ }
+ hStream->ByteAlign();
+ hStream->SkipBits(dwSharedObjTotal);
+ hStream->ByteAlign();
+ return TRUE;
+}
+FX_BOOL CPDF_HintTables::GetPagePos(int index,
+ FX_FILESIZE& szPageStartPos,
+ FX_FILESIZE& szPageLength,
+ FX_DWORD& dwObjNum) {
+ if (!m_pLinearizedDict)
+ return FALSE;
+ szPageStartPos = m_szPageOffsetArray[index];
+ szPageLength = GetItemLength(index, m_szPageOffsetArray);
+ CPDF_Object* pFirstPageNum =
+ m_pLinearizedDict->GetElementValue(FX_BSTRC("P"));
+ int nFirstPageNum = pFirstPageNum ? pFirstPageNum->GetInteger() : 0;
+ CPDF_Object* pFirstPageObjNum =
+ m_pLinearizedDict->GetElementValue(FX_BSTRC("O"));
+ if (!pFirstPageObjNum)
+ return FALSE;
+ int nFirstPageObjNum = pFirstPageObjNum->GetInteger();
+ if (index == nFirstPageNum) {
+ dwObjNum = nFirstPageObjNum;
+ return TRUE;
+ }
+ // The object number of remaining pages starts from 1.
+ dwObjNum = 1;
+ for (int i = 0; i < index; ++i) {
+ if (i == nFirstPageNum)
+ continue;
+ dwObjNum += m_dwDeltaNObjsArray[i];
+ }
+ return TRUE;
+}
+FX_BOOL CPDF_HintTables::CheckPage(int index, IFX_DownloadHints* pHints) {
+ if (!m_pLinearizedDict)
+ return FALSE;
+ CPDF_Object* pFirstAvailPage =
+ m_pLinearizedDict->GetElementValue(FX_BSTRC("P"));
+ int nFirstAvailPage = pFirstAvailPage ? pFirstAvailPage->GetInteger() : 0;
+ if (index == nFirstAvailPage)
+ return TRUE;
+ FX_DWORD dwLength = GetItemLength(index, m_szPageOffsetArray);
+ if (!dwLength ||
+ !m_pDataAvail->IsDataAvail(m_szPageOffsetArray[index], dwLength,
+ pHints)) {
+ return FALSE;
+ }
+ // Download data of shared objects in the page.
+ FX_DWORD offset = 0;
+ for (int i = 0; i < index; ++i) {
+ offset += m_dwNSharedObjsArray[i];
+ }
+ CPDF_Object* pFirstPageObj =
+ m_pLinearizedDict->GetElementValue(FX_BSTRC("O"));
+ int nFirstPageObjNum = pFirstPageObj ? pFirstPageObj->GetInteger() : -1;
+ if (nFirstPageObjNum < 0)
+ return FALSE;
+ FX_DWORD dwIndex = 0;
+ FX_DWORD dwObjNum = 0;
+ for (int j = 0; j < m_dwNSharedObjsArray[index]; ++j) {
+ dwIndex = m_dwIdentifierArray[offset + j];
+ dwObjNum = m_dwSharedObjNumArray[dwIndex];
+ if (dwObjNum >= nFirstPageObjNum &&
+ dwObjNum < nFirstPageObjNum + m_nFirstPageSharedObjs) {
+ continue;
+ }
+ dwLength = GetItemLength(dwIndex, m_szSharedObjOffsetArray);
+ if (!dwLength ||
+ !m_pDataAvail->IsDataAvail(m_szSharedObjOffsetArray[dwIndex], dwLength,
+ pHints)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+FX_BOOL CPDF_HintTables::LoadHintStream(CPDF_Stream* pHintStream) {
+ if (!pHintStream || !m_pLinearizedDict)
+ return FALSE;
+ CPDF_Dictionary* pDict = pHintStream->GetDict();
+ CPDF_Object* pOffset = pDict ? pDict->GetElement(FX_BSTRC("S")) : nullptr;
+ if (!pOffset || pOffset->GetType() != PDFOBJ_NUMBER)
+ return FALSE;
+ CPDF_StreamAcc acc;
+ acc.LoadAllData(pHintStream);
+ FX_DWORD size = acc.GetSize();
+ // The header section of page offset hint table is 36 bytes.
+ // The header section of shared object hint table is 24 bytes.
+ // Hint table has at least 60 bytes.
+ const FX_DWORD MIN_STREAM_LEN = 60;
+ if (size < MIN_STREAM_LEN || size < pOffset->GetInteger() ||
+ !pOffset->GetInteger()) {
+ return FALSE;
+ }
+ CFX_BitStream bs;
+ bs.Init(acc.GetData(), size);
+ return ReadPageHintTable(&bs) && ReadSharedObjHintTable(&bs);
+}
+int CPDF_HintTables::ReadPrimaryHintStreamOffset() const {
+ if (!m_pLinearizedDict)
+ return -1;
+ CPDF_Array* pRange = m_pLinearizedDict->GetArray(FX_BSTRC("H"));
+ if (!pRange)
+ return -1;
+ CPDF_Object* pStreamOffset = pRange->GetElementValue(0);
+ if (!pStreamOffset)
+ return -1;
+ return pStreamOffset->GetInteger();
+}
+int CPDF_HintTables::ReadPrimaryHintStreamLength() const {
+ if (!m_pLinearizedDict)
+ return -1;
+ CPDF_Array* pRange = m_pLinearizedDict->GetArray(FX_BSTRC("H"));
+ if (!pRange)
+ return -1;
+ CPDF_Object* pStreamLen = pRange->GetElementValue(1);
+ if (!pStreamLen)
+ return -1;
+ return pStreamLen->GetInteger();
+}
« no previous file with comments | « core/include/fpdfapi/fpdf_parser.h ('k') | core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_embeddertest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698