| Index: experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp
|
| ===================================================================
|
| --- experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp (revision 10419)
|
| +++ experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp (working copy)
|
| @@ -123,7 +123,7 @@
|
| bool storeCatalog = true;
|
| while (xrefByteOffset >= 0) {
|
| const unsigned char* trailerStart = readCrossReferenceSection(fFileContent + xrefByteOffset, xrefstartKeywordLine);
|
| - xrefByteOffset = readTrailer(trailerStart, xrefstartKeywordLine, storeCatalog);
|
| + readTrailer(trailerStart, xrefstartKeywordLine, storeCatalog, &xrefByteOffset, false);
|
| storeCatalog = false;
|
| }
|
|
|
| @@ -141,6 +141,12 @@
|
| }
|
| }
|
|
|
| + // TODO(edisonn): clean up this doc, or better, let the caller call again and build a new doc
|
| + // caller should be a static function.
|
| + if (pages() == 0) {
|
| + loadWithoutXRef();
|
| + }
|
| +
|
| // TODO(edisonn): corrupted pdf, read it from beginning and rebuild (xref, trailer, or just reall all objects)
|
| // 0 pages
|
|
|
| @@ -148,6 +154,67 @@
|
| // and resolve references?... or not ...
|
| }
|
|
|
| +void SkNativeParsedPDF::loadWithoutXRef() {
|
| + const unsigned char* current = fFileContent;
|
| + const unsigned char* end = fFileContent + fContentLength;
|
| +
|
| + // TODO(edisonn): read pdf version
|
| + current = ignoreLine(current, end);
|
| +
|
| + current = skipPdfWhiteSpaces(0, current, end);
|
| + while (current < end) {
|
| + SkPdfObject token;
|
| + current = nextObject(0, current, end, &token, NULL, NULL);
|
| + if (token.isInteger()) {
|
| + int id = (int)token.intValue();
|
| +
|
| + token.reset();
|
| + current = nextObject(0, current, end, &token, NULL, NULL);
|
| + // int generation = (int)token.intValue(); // TODO(edisonn): ignored for now
|
| +
|
| + token.reset();
|
| + current = nextObject(0, current, end, &token, NULL, NULL);
|
| + // TODO(edisonn): must be obj, return error if not? ignore ?
|
| + if (!token.isKeyword("obj")) {
|
| + continue;
|
| + }
|
| +
|
| + while (fObjects.count() < id + 1) {
|
| + reset(fObjects.append());
|
| + }
|
| +
|
| + fObjects[id].fOffset = current - fFileContent;
|
| +
|
| + SkPdfObject* obj = fAllocator->allocObject();
|
| + current = nextObject(0, current, end, obj, fAllocator, this);
|
| +
|
| + fObjects[id].fResolvedReference = obj;
|
| + fObjects[id].fObj = obj;
|
| +
|
| + // set objects
|
| + } else if (token.isKeyword("trailer")) {
|
| + long dummy;
|
| + current = readTrailer(current, end, true, &dummy, true);
|
| + } else if (token.isKeyword("startxref")) {
|
| + token.reset();
|
| + current = nextObject(0, current, end, &token, NULL, NULL); // ignore
|
| + }
|
| +
|
| + current = skipPdfWhiteSpaces(0, current, end);
|
| + }
|
| +
|
| + if (fRootCatalogRef) {
|
| + fRootCatalog = (SkPdfCatalogDictionary*)resolveReference(fRootCatalogRef);
|
| + if (fRootCatalog->isDictionary() && fRootCatalog->valid()) {
|
| + SkPdfPageTreeNodeDictionary* tree = fRootCatalog->Pages(this);
|
| + if (tree && tree->isDictionary() && tree->valid()) {
|
| + fillPages(tree);
|
| + }
|
| + }
|
| + }
|
| +
|
| +}
|
| +
|
| // TODO(edisonn): NYI
|
| SkNativeParsedPDF::~SkNativeParsedPDF() {
|
| sk_free((void*)fFileContent);
|
| @@ -208,43 +275,47 @@
|
| return current;
|
| }
|
|
|
| -long SkNativeParsedPDF::readTrailer(const unsigned char* trailerStart, const unsigned char* trailerEnd, bool storeCatalog) {
|
| - SkPdfObject trailerKeyword;
|
| - // TODO(edisonn): use null allocator, and let it just fail if memory
|
| - // needs allocated (but no crash)!
|
| - const unsigned char* current =
|
| - nextObject(0, trailerStart, trailerEnd, &trailerKeyword, NULL, NULL);
|
| +const unsigned char* SkNativeParsedPDF::readTrailer(const unsigned char* trailerStart, const unsigned char* trailerEnd, bool storeCatalog, long* prev, bool skipKeyword) {
|
| + *prev = -1;
|
|
|
| - if (!trailerKeyword.isKeyword() || strlen("trailer") != trailerKeyword.lenstr() ||
|
| - strncmp(trailerKeyword.c_str(), "trailer", strlen("trailer")) != 0) {
|
| - // TODO(edisonn): report warning, rebuild trailer from objects.
|
| - return -1;
|
| + const unsigned char* current = trailerStart;
|
| + if (!skipKeyword) {
|
| + SkPdfObject trailerKeyword;
|
| + // TODO(edisonn): use null allocator, and let it just fail if memory
|
| + // needs allocated (but no crash)!
|
| + current = nextObject(0, current, trailerEnd, &trailerKeyword, NULL, NULL);
|
| +
|
| + if (!trailerKeyword.isKeyword() || strlen("trailer") != trailerKeyword.lenstr() ||
|
| + strncmp(trailerKeyword.c_str(), "trailer", strlen("trailer")) != 0) {
|
| + // TODO(edisonn): report warning, rebuild trailer from objects.
|
| + return current;
|
| + }
|
| }
|
|
|
| SkPdfObject token;
|
| current = nextObject(0, current, trailerEnd, &token, fAllocator, NULL);
|
| if (!token.isDictionary()) {
|
| - return -1;
|
| + return current;
|
| }
|
| SkPdfFileTrailerDictionary* trailer = (SkPdfFileTrailerDictionary*)&token;
|
| if (!trailer->valid()) {
|
| - return -1;
|
| + return current;
|
| }
|
|
|
| if (storeCatalog) {
|
| const SkPdfObject* ref = trailer->Root(NULL);
|
| if (ref == NULL || !ref->isReference()) {
|
| // TODO(edisonn): oops, we have to fix the corrup pdf file
|
| - return -1;
|
| + return current;
|
| }
|
| fRootCatalogRef = ref;
|
| }
|
|
|
| if (trailer->has_Prev()) {
|
| - return (long)trailer->Prev(NULL);
|
| + *prev = (long)trailer->Prev(NULL);
|
| }
|
|
|
| - return -1;
|
| + return current;
|
| }
|
|
|
| void SkNativeParsedPDF::addCrossSectionInfo(int id, int generation, int offset, bool isFreed) {
|
| @@ -255,6 +326,7 @@
|
|
|
| fObjects[id].fOffset = offset;
|
| fObjects[id].fObj = NULL;
|
| + fObjects[id].fResolvedReference = NULL;
|
| }
|
|
|
| SkPdfObject* SkNativeParsedPDF::readObject(int id/*, int expectedGeneration*/) {
|
|
|