1cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com/* 2cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * Copyright 2013 Google Inc. 3cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * 4cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * Use of this source code is governed by a BSD-style license that can be 5cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com * found in the LICENSE file. 6cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com */ 7cf2cfa174ca878c144e17e9fc60ca8e9070d7dededisonn@google.com 83aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com#include "SkPdfNativeDoc.h" 9571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 10571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com#include <stdio.h> 11571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com#include <string.h> 12571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com#include <sys/types.h> 13571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com#include <sys/stat.h> 14571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 15c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com#include "SkPdfMapper_autogen.h" 16c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com#include "SkPdfNativeObject.h" 17c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com#include "SkPdfNativeTokenizer.h" 18c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com#include "SkPdfReporter.h" 19c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com#include "SkStream.h" 20c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com 2133f11b6fcdb7dfce27f953803be40fbacedc7450edisonn@google.com// TODO(edisonn): for some reason on mac these files are found here, but are found from headers 2233f11b6fcdb7dfce27f953803be40fbacedc7450edisonn@google.com//#include "SkPdfFileTrailerDictionary_autogen.h" 2333f11b6fcdb7dfce27f953803be40fbacedc7450edisonn@google.com//#include "SkPdfCatalogDictionary_autogen.h" 2433f11b6fcdb7dfce27f953803be40fbacedc7450edisonn@google.com//#include "SkPdfPageObjectDictionary_autogen.h" 2533f11b6fcdb7dfce27f953803be40fbacedc7450edisonn@google.com//#include "SkPdfPageTreeNodeDictionary_autogen.h" 2633f11b6fcdb7dfce27f953803be40fbacedc7450edisonn@google.com#include "SkPdfHeaders_autogen.h" 2733f11b6fcdb7dfce27f953803be40fbacedc7450edisonn@google.com 28a3356fce903ff75dc332b53dd3a860ba810b9519edisonn@google.comstatic long getFileSize(const char* filename) 29571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com{ 30571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com struct stat stat_buf; 31571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com int rc = stat(filename, &stat_buf); 32a3356fce903ff75dc332b53dd3a860ba810b9519edisonn@google.com return rc == 0 ? (long)stat_buf.st_size : -1; 33571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 34571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 352ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.comstatic const unsigned char* lineHome(const unsigned char* start, const unsigned char* current) { 36571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com while (current > start && !isPdfEOL(*(current - 1))) { 37571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com current--; 38571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 39571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return current; 40571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 41571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 42c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.comstatic const unsigned char* previousLineHome(const unsigned char* start, 43c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com const unsigned char* current) { 44571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (current > start && isPdfEOL(*(current - 1))) { 45571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com current--; 46571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 47571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 48571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com // allows CR+LF, LF+CR but not two CR+CR or LF+LF 49571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (current > start && isPdfEOL(*(current - 1)) && *current != *(current - 1)) { 50571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com current--; 51571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 52571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 53571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com while (current > start && !isPdfEOL(*(current - 1))) { 54571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com current--; 55571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 56571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 57571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return current; 58571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 59571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 602ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.comstatic const unsigned char* ignoreLine(const unsigned char* current, const unsigned char* end) { 61571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com while (current < end && !isPdfEOL(*current)) { 62571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com current++; 63571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 64571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com current++; 65571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (current < end && isPdfEOL(*current) && *current != *(current - 1)) { 66571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com current++; 67571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 68571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return current; 69571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 70571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 713aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfNativeDoc* gDoc = NULL; 72571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 733aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfNativeDoc::SkPdfNativeDoc(SkStream* stream) 74147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com : fAllocator(new SkPdfAllocator()) 75147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com , fFileContent(NULL) 76147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com , fContentLength(0) 77147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com , fRootCatalogRef(NULL) 78147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com , fRootCatalog(NULL) { 79147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com size_t size = stream->getLength(); 80147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com void* ptr = sk_malloc_throw(size); 81147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com stream->read(ptr, size); 82147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com 83147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com init(ptr, size); 84147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com} 85147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com 863aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfNativeDoc::SkPdfNativeDoc(const char* path) 87432640ae0b9f4bc40e3447651ff5be0cd2be6b11edisonn@google.com : fAllocator(new SkPdfAllocator()) 88147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com , fFileContent(NULL) 89147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com , fContentLength(0) 90432640ae0b9f4bc40e3447651ff5be0cd2be6b11edisonn@google.com , fRootCatalogRef(NULL) 91432640ae0b9f4bc40e3447651ff5be0cd2be6b11edisonn@google.com , fRootCatalog(NULL) { 92222382b30a176db9d9044d9df1ae14e0fbe27181edisonn@google.com gDoc = this; 93571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com FILE* file = fopen(path, "r"); 94e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com // TODO(edisonn): put this in a function that can return NULL 95e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com if (file) { 96e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com size_t size = getFileSize(path); 97e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com void* content = sk_malloc_throw(size); 98e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com bool ok = (0 != fread(content, size, 1, file)); 99e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com fclose(file); 100e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com if (!ok) { 101e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com sk_free(content); 102c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReport(kFatalError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, 103c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "could not read file", NULL, NULL); 104e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com // TODO(edisonn): not nice to return like this from constructor, create a static 105e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com // function that can report NULL for failures. 106e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com return; // Doc will have 0 pages 107e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com } 108e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com 109e57c62d039cbd67a4e52776b3e95c5d002b818d2edisonn@google.com init(content, size); 110620edc503938e3bfb7621923c2f50e77451fecaeedisonn@google.com } 111147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com} 112147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com 1133aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comvoid SkPdfNativeDoc::init(const void* bytes, size_t length) { 114147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com fFileContent = (const unsigned char*)bytes; 115147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com fContentLength = length; 1162ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com const unsigned char* eofLine = lineHome(fFileContent, fFileContent + fContentLength - 1); 1172ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com const unsigned char* xrefByteOffsetLine = previousLineHome(fFileContent, eofLine); 1182ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com const unsigned char* xrefstartKeywordLine = previousLineHome(fFileContent, xrefByteOffsetLine); 119571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 120571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (strcmp((char*)xrefstartKeywordLine, "startxref") != 0) { 121c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReport(kWarning_SkPdfIssueSeverity, kMissingToken_SkPdfIssue, 122c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "Could not find startxref", NULL, NULL); 123571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 124571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 125571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com long xrefByteOffset = atol((const char*)xrefByteOffsetLine); 126571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 127571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com bool storeCatalog = true; 128571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com while (xrefByteOffset >= 0) { 129909228992c1671ea7451d1c6bc588a8ec991841escroggo@google.com const unsigned char* trailerStart = this->readCrossReferenceSection(fFileContent + xrefByteOffset, 130909228992c1671ea7451d1c6bc588a8ec991841escroggo@google.com xrefstartKeywordLine); 13124cdf13b314889a2bfa50969c5a85b74aa49ea1dedisonn@google.com xrefByteOffset = -1; 13224cdf13b314889a2bfa50969c5a85b74aa49ea1dedisonn@google.com if (trailerStart < xrefstartKeywordLine) { 133909228992c1671ea7451d1c6bc588a8ec991841escroggo@google.com this->readTrailer(trailerStart, xrefstartKeywordLine, storeCatalog, &xrefByteOffset, false); 13424cdf13b314889a2bfa50969c5a85b74aa49ea1dedisonn@google.com storeCatalog = false; 13524cdf13b314889a2bfa50969c5a85b74aa49ea1dedisonn@google.com } 136571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 137571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 138571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com // TODO(edisonn): warn/error expect fObjects[fRefCatalogId].fGeneration == fRefCatalogGeneration 139571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com // TODO(edisonn): security, verify that SkPdfCatalogDictionary is indeed using mapper 1403aac1f9f308192f3787265830fe86ce8874e7382edisonn@google.com 141432640ae0b9f4bc40e3447651ff5be0cd2be6b11edisonn@google.com if (fRootCatalogRef) { 142432640ae0b9f4bc40e3447651ff5be0cd2be6b11edisonn@google.com fRootCatalog = (SkPdfCatalogDictionary*)resolveReference(fRootCatalogRef); 143608c35e5c4ce61a79b7a0567c8eca569332c2ddeedisonn@google.com if (fRootCatalog != NULL && fRootCatalog->isDictionary() && fRootCatalog->valid()) { 1448bad7375d7e0ebe28af4d905665f34227843bd16edisonn@google.com SkPdfPageTreeNodeDictionary* tree = fRootCatalog->Pages(this); 1458bad7375d7e0ebe28af4d905665f34227843bd16edisonn@google.com if (tree && tree->isDictionary() && tree->valid()) { 1468bad7375d7e0ebe28af4d905665f34227843bd16edisonn@google.com fillPages(tree); 1478bad7375d7e0ebe28af4d905665f34227843bd16edisonn@google.com } 1488bad7375d7e0ebe28af4d905665f34227843bd16edisonn@google.com } 149432640ae0b9f4bc40e3447651ff5be0cd2be6b11edisonn@google.com } 1503aac1f9f308192f3787265830fe86ce8874e7382edisonn@google.com 1514ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com if (pages() == 0) { 152c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // TODO(edisonn): probably it would be better to return NULL and make a clean document. 1534ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com loadWithoutXRef(); 1544ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com } 1554ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 156c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // TODO(edisonn): corrupted pdf, read it from beginning and rebuild 157c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // (xref, trailer, or just read all objects) 1583aac1f9f308192f3787265830fe86ce8874e7382edisonn@google.com} 1593aac1f9f308192f3787265830fe86ce8874e7382edisonn@google.com 1603aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comvoid SkPdfNativeDoc::loadWithoutXRef() { 1614ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com const unsigned char* current = fFileContent; 1624ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com const unsigned char* end = fFileContent + fContentLength; 1634ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 1644ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com // TODO(edisonn): read pdf version 1654ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com current = ignoreLine(current, end); 1664ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 167598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = skipPdfWhiteSpaces(current, end); 1684ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com while (current < end) { 1693aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject token; 170598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, end, &token, NULL, NULL); 1714ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com if (token.isInteger()) { 1724ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com int id = (int)token.intValue(); 1734ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 1744ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com token.reset(); 175598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, end, &token, NULL, NULL); 176c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // TODO(edisonn): generation ignored for now (used in pdfs with updates) 177c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // int generation = (int)token.intValue(); 1784ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 1794ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com token.reset(); 180598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, end, &token, NULL, NULL); 181c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // TODO(edisonn): keywork must be "obj". Add ability to report error instead ignoring. 1824ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com if (!token.isKeyword("obj")) { 183c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReport(kWarning_SkPdfIssueSeverity, kMissingToken_SkPdfIssue, 184c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "Could not find obj", NULL, NULL); 1854ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com continue; 1864ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com } 1874ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 1884ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com while (fObjects.count() < id + 1) { 1894ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com reset(fObjects.append()); 1904ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com } 1914ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 1924ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com fObjects[id].fOffset = current - fFileContent; 1934ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 1943aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject* obj = fAllocator->allocObject(); 195598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, end, obj, fAllocator, this); 1964ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 1974ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com fObjects[id].fResolvedReference = obj; 1984ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com fObjects[id].fObj = obj; 199af54a513a5b7723b53f61730afe0ad6256881749edisonn@google.com fObjects[id].fIsReferenceResolved = true; 2004ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com } else if (token.isKeyword("trailer")) { 2014ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com long dummy; 2024ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com current = readTrailer(current, end, true, &dummy, true); 2034ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com } else if (token.isKeyword("startxref")) { 2044ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com token.reset(); 205c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com current = nextObject(current, end, &token, NULL, NULL); // ignore startxref 2064ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com } 2074ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 208598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = skipPdfWhiteSpaces(current, end); 2094ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com } 2104ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 211c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // TODO(edisonn): quick hack, detect root catalog. When we implement linearized support we 212c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // might not need it. 2134f898b78bb1c04e4763eca59a6e1defef555e696edisonn@google.com if (!fRootCatalogRef) { 2144f898b78bb1c04e4763eca59a6e1defef555e696edisonn@google.com for (unsigned int i = 0 ; i < objects(); i++) { 2153aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject* obj = object(i); 2163aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject* root = (obj && obj->isDictionary()) ? obj->get("Root") : NULL; 2174f898b78bb1c04e4763eca59a6e1defef555e696edisonn@google.com if (root && root->isReference()) { 2184f898b78bb1c04e4763eca59a6e1defef555e696edisonn@google.com fRootCatalogRef = root; 2194f898b78bb1c04e4763eca59a6e1defef555e696edisonn@google.com } 2204f898b78bb1c04e4763eca59a6e1defef555e696edisonn@google.com } 2214f898b78bb1c04e4763eca59a6e1defef555e696edisonn@google.com } 2224f898b78bb1c04e4763eca59a6e1defef555e696edisonn@google.com 2234ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com if (fRootCatalogRef) { 2244ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com fRootCatalog = (SkPdfCatalogDictionary*)resolveReference(fRootCatalogRef); 225608c35e5c4ce61a79b7a0567c8eca569332c2ddeedisonn@google.com if (fRootCatalog != NULL && fRootCatalog->isDictionary() && fRootCatalog->valid()) { 2264ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com SkPdfPageTreeNodeDictionary* tree = fRootCatalog->Pages(this); 2274ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com if (tree && tree->isDictionary() && tree->valid()) { 2284ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com fillPages(tree); 2294ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com } 2304ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com } 2314ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com } 2324ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 2334f898b78bb1c04e4763eca59a6e1defef555e696edisonn@google.com 2344ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com} 2354ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 2363aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfNativeDoc::~SkPdfNativeDoc() { 237147adb10f7f80ae721879e08474fd575e719487cedisonn@google.com sk_free((void*)fFileContent); 238571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com delete fAllocator; 239571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 240571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 241c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.comconst unsigned char* SkPdfNativeDoc::readCrossReferenceSection(const unsigned char* xrefStart, 242c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com const unsigned char* trailerEnd) { 2433aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject xref; 244598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com const unsigned char* current = nextObject(xrefStart, trailerEnd, &xref, NULL, NULL); 2452273f9b45fb78b0cc7df81f96f74b0c3c0e6cc37edisonn@google.com 2462273f9b45fb78b0cc7df81f96f74b0c3c0e6cc37edisonn@google.com if (!xref.isKeyword("xref")) { 247c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReport(kWarning_SkPdfIssueSeverity, kMissingToken_SkPdfIssue, "Could not find sref", 248c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com NULL, NULL); 2492273f9b45fb78b0cc7df81f96f74b0c3c0e6cc37edisonn@google.com return trailerEnd; 2502273f9b45fb78b0cc7df81f96f74b0c3c0e6cc37edisonn@google.com } 251571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 2523aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject token; 253571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com while (current < trailerEnd) { 254571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com token.reset(); 2552ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com const unsigned char* previous = current; 256598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, trailerEnd, &token, NULL, NULL); 257571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (!token.isInteger()) { 258c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReport(kInfo_SkPdfIssueSeverity, kNoIssue_SkPdfIssue, 259c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "Done readCrossReferenceSection", NULL, NULL); 260571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return previous; 261571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 262571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 263a3356fce903ff75dc332b53dd3a860ba810b9519edisonn@google.com int startId = (int)token.intValue(); 264571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com token.reset(); 265598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, trailerEnd, &token, NULL, NULL); 266571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 267571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (!token.isInteger()) { 268c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readCrossReferenceSection", 269c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com &token, SkPdfNativeObject::kInteger_PdfObjectType, NULL); 270571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return current; 271571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 272571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 273a3356fce903ff75dc332b53dd3a860ba810b9519edisonn@google.com int entries = (int)token.intValue(); 274571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 275571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com for (int i = 0; i < entries; i++) { 276571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com token.reset(); 277598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, trailerEnd, &token, NULL, NULL); 278571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (!token.isInteger()) { 279c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, 280c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "readCrossReferenceSection", 281c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com &token, SkPdfNativeObject::kInteger_PdfObjectType, NULL); 282571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return current; 283571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 284a3356fce903ff75dc332b53dd3a860ba810b9519edisonn@google.com int offset = (int)token.intValue(); 285571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 286571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com token.reset(); 287598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, trailerEnd, &token, NULL, NULL); 288571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (!token.isInteger()) { 289c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, 290c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "readCrossReferenceSection", 291c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com &token, SkPdfNativeObject::kInteger_PdfObjectType, NULL); 292571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return current; 293571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 294a3356fce903ff75dc332b53dd3a860ba810b9519edisonn@google.com int generation = (int)token.intValue(); 295571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 296571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com token.reset(); 297598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, trailerEnd, &token, NULL, NULL); 298c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com if (!token.isKeyword() || token.lenstr() != 1 || 299c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com (*token.c_str() != 'f' && *token.c_str() != 'n')) { 300c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, 301c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "readCrossReferenceSection: f or n expected", 302c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com &token, SkPdfNativeObject::kKeyword_PdfObjectType, NULL); 303571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return current; 304571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 305571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 306909228992c1671ea7451d1c6bc588a8ec991841escroggo@google.com this->addCrossSectionInfo(startId + i, generation, offset, *token.c_str() == 'f'); 307571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 308571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 309c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReport(kInfo_SkPdfIssueSeverity, kNoIssue_SkPdfIssue, 310c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "Unexpected end of readCrossReferenceSection", NULL, NULL); 311571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return current; 312571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 313571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 314c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.comconst unsigned char* SkPdfNativeDoc::readTrailer(const unsigned char* trailerStart, 315c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com const unsigned char* trailerEnd, 316c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com bool storeCatalog, long* prev, bool skipKeyword) { 3174ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com *prev = -1; 3184ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 3194ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com const unsigned char* current = trailerStart; 3204ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com if (!skipKeyword) { 3213aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject trailerKeyword; 322c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // Use null allocator, and let it just fail if memory, it should not crash. 323598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, trailerEnd, &trailerKeyword, NULL, NULL); 3244ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com 3254ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com if (!trailerKeyword.isKeyword() || strlen("trailer") != trailerKeyword.lenstr() || 3264ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com strncmp(trailerKeyword.c_str(), "trailer", strlen("trailer")) != 0) { 327c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, 328c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "readTrailer: trailer keyword expected", 329c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com &trailerKeyword, 330c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfNativeObject::kKeyword_PdfObjectType, NULL); 3314ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com return current; 3324ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com } 3332ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com } 334571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 3353aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject token; 336598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, trailerEnd, &token, fAllocator, NULL); 337432640ae0b9f4bc40e3447651ff5be0cd2be6b11edisonn@google.com if (!token.isDictionary()) { 3384ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com return current; 339432640ae0b9f4bc40e3447651ff5be0cd2be6b11edisonn@google.com } 340571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com SkPdfFileTrailerDictionary* trailer = (SkPdfFileTrailerDictionary*)&token; 341432640ae0b9f4bc40e3447651ff5be0cd2be6b11edisonn@google.com if (!trailer->valid()) { 3424ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com return current; 343432640ae0b9f4bc40e3447651ff5be0cd2be6b11edisonn@google.com } 344571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 345571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (storeCatalog) { 3463aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject* ref = trailer->Root(NULL); 347571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (ref == NULL || !ref->isReference()) { 348c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, 349c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "readTrailer: unexpected root reference", 350c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com ref, SkPdfNativeObject::kReference_PdfObjectType, NULL); 3514ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com return current; 352571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 353571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com fRootCatalogRef = ref; 354571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 355571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 356571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (trailer->has_Prev()) { 3574ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com *prev = (long)trailer->Prev(NULL); 358571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 359571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 3604ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com return current; 361571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 362571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 3633aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comvoid SkPdfNativeDoc::addCrossSectionInfo(int id, int generation, int offset, bool isFreed) { 364c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // TODO(edisonn): security here, verify id 365571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com while (fObjects.count() < id + 1) { 366909228992c1671ea7451d1c6bc588a8ec991841escroggo@google.com this->reset(fObjects.append()); 367571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 368571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 369571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com fObjects[id].fOffset = offset; 370571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com fObjects[id].fObj = NULL; 3714ef4bed00efd247a0ea005b95b7239a9d4c14c68edisonn@google.com fObjects[id].fResolvedReference = NULL; 372f68aed33819cbc98a95edeadde1da9303eca7fb2edisonn@google.com fObjects[id].fIsReferenceResolved = false; 373571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 374571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 3753aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfNativeObject* SkPdfNativeDoc::readObject(int id/*, int expectedGeneration*/) { 376571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com long startOffset = fObjects[id].fOffset; 377571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com //long endOffset = fObjects[id].fOffsetEnd; 378571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com // TODO(edisonn): use hinted endOffset 3792ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com const unsigned char* current = fFileContent + startOffset; 3802ccc3afa474f9485c39c2e863252ddaa3f35724bedisonn@google.com const unsigned char* end = fFileContent + fContentLength; 381571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 3825f008652f69ce7809b920b9fa573bc72216acd51scroggo@google.com SkPdfNativeTokenizer tokenizer(current, (int) (end - current), fAllocator, this); 383571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 3843aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject idObj; 3853aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject generationObj; 3863aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject objKeyword; 3873aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject* dict = fAllocator->allocObject(); 388571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 389598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, end, &idObj, NULL, NULL); 390571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (current >= end) { 391c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, "reading id", 392c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com NULL, NULL); 393571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return NULL; 394571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 395571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 396598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, end, &generationObj, NULL, NULL); 397571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (current >= end) { 398c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, 399c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "reading generation", NULL, NULL); 400571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return NULL; 401571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 402571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 403598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, end, &objKeyword, NULL, NULL); 404571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (current >= end) { 405c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, 406c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "reading keyword obj", NULL, NULL); 407571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return NULL; 408571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 409571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 410af54a513a5b7723b53f61730afe0ad6256881749edisonn@google.com if (!idObj.isInteger() || id != idObj.intValue()) { 411c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, "readObject: unexpected id", 412c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com &idObj, SkPdfNativeObject::kInteger_PdfObjectType, NULL); 413af54a513a5b7723b53f61730afe0ad6256881749edisonn@google.com } 414af54a513a5b7723b53f61730afe0ad6256881749edisonn@google.com 415af54a513a5b7723b53f61730afe0ad6256881749edisonn@google.com // TODO(edisonn): verify that the generation is the right one 416af54a513a5b7723b53f61730afe0ad6256881749edisonn@google.com if (!generationObj.isInteger() /* || generation != generationObj.intValue()*/) { 417c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, 418c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "readObject: unexpected generation", 419c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com &generationObj, SkPdfNativeObject::kInteger_PdfObjectType, NULL); 420571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 421571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 422571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (!objKeyword.isKeyword() || strcmp(objKeyword.c_str(), "obj") != 0) { 423c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReportUnexpectedType(kIgnoreError_SkPdfIssueSeverity, 424c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "readObject: unexpected obj keyword", 425c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com &objKeyword, SkPdfNativeObject::kKeyword_PdfObjectType, NULL); 426571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 427571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 428598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com current = nextObject(current, end, dict, fAllocator, this); 429571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 430c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // TODO(edisonn): report warning/error - verify that the last token is endobj 431571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 432571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return dict; 433571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 434571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 4353aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comvoid SkPdfNativeDoc::fillPages(SkPdfPageTreeNodeDictionary* tree) { 436b0145ce60ea1a3bacc786ec1285218c6fe70c8a3edisonn@google.com SkPdfArray* kids = tree->Kids(this); 437571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (kids == NULL) { 438571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com *fPages.append() = (SkPdfPageObjectDictionary*)tree; 439571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return; 440571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 441571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 4425f008652f69ce7809b920b9fa573bc72216acd51scroggo@google.com int cnt = (int) kids->size(); 443571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com for (int i = 0; i < cnt; i++) { 4443aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject* obj = resolveReference(kids->objAtAIndex(i)); 4453aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com if (fMapper->mapPageObjectDictionary(obj) != kPageObjectDictionary_SkPdfNativeObjectType) { 446571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com *fPages.append() = (SkPdfPageObjectDictionary*)obj; 447571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } else { 448571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com // TODO(edisonn): verify that it is a page tree indeed 449571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com fillPages((SkPdfPageTreeNodeDictionary*)obj); 450571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 451571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 452571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 453571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 4543aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comint SkPdfNativeDoc::pages() const { 455571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return fPages.count(); 456571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 457571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 4583aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfPageObjectDictionary* SkPdfNativeDoc::page(int page) { 45988fc03dd1f47ad33b08d60c47013de860f8fa69fedisonn@google.com SkASSERT(page >= 0 && page < fPages.count()); 46088fc03dd1f47ad33b08d60c47013de860f8fa69fedisonn@google.com return fPages[page]; 46188fc03dd1f47ad33b08d60c47013de860f8fa69fedisonn@google.com} 46288fc03dd1f47ad33b08d60c47013de860f8fa69fedisonn@google.com 46388fc03dd1f47ad33b08d60c47013de860f8fa69fedisonn@google.com 4643aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfResourceDictionary* SkPdfNativeDoc::pageResources(int page) { 46588fc03dd1f47ad33b08d60c47013de860f8fa69fedisonn@google.com SkASSERT(page >= 0 && page < fPages.count()); 466571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return fPages[page]->Resources(this); 467571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 468571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 469c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com// TODO(edisonn): Partial implemented. 470c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com// Move the logics directly in the code generator for inheritable and default values? 4713aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkRect SkPdfNativeDoc::MediaBox(int page) { 472571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com SkPdfPageObjectDictionary* current = fPages[page]; 473571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com while (!current->has_MediaBox() && current->has_Parent()) { 474571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com current = (SkPdfPageObjectDictionary*)current->Parent(this); 475571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 476571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (current) { 477571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return current->MediaBox(this); 478571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 479571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return SkRect::MakeEmpty(); 480571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 481571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 4823aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comsize_t SkPdfNativeDoc::objects() const { 483571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return fObjects.count(); 484571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 485571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 4863aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfNativeObject* SkPdfNativeDoc::object(int i) { 487571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com SkASSERT(!(i < 0 || i > fObjects.count())); 488571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 489571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (i < 0 || i > fObjects.count()) { 490571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return NULL; 491571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 492571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 493571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (fObjects[i].fObj == NULL) { 494571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com fObjects[i].fObj = readObject(i); 495c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // TODO(edisonn): For perf, when we read the cross reference sections, we should take 496c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // advantage of the boundaries of known objects, to minimize the risk of just parsing a bad 497c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // stream, and fail quickly, in case we default to sequential stream read. 498571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 499571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 500571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return fObjects[i].fObj; 501571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 502571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 5033aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comconst SkPdfMapper* SkPdfNativeDoc::mapper() const { 504571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return fMapper; 505571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 506571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 5073aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfReal* SkPdfNativeDoc::createReal(double value) const { 5083aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject* obj = fAllocator->allocObject(); 509598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com SkPdfNativeObject::makeReal(value, obj); 510c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com TRACK_OBJECT_SRC(obj); 511571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return (SkPdfReal*)obj; 512571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 513571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 5143aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfInteger* SkPdfNativeDoc::createInteger(int value) const { 5153aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject* obj = fAllocator->allocObject(); 516598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com SkPdfNativeObject::makeInteger(value, obj); 517c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com TRACK_OBJECT_SRC(obj); 518571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return (SkPdfInteger*)obj; 519571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 520571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 5213aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfString* SkPdfNativeDoc::createString(const unsigned char* sz, size_t len) const { 5223aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com SkPdfNativeObject* obj = fAllocator->allocObject(); 523598cf5d3cfc428108cf21ab45d73a995d7e5c2a8edisonn@google.com SkPdfNativeObject::makeString(sz, len, obj); 524c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com TRACK_OBJECT_SRC(obj); 525571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return (SkPdfString*)obj; 526571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 527571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 5283aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfAllocator* SkPdfNativeDoc::allocator() const { 529571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return fAllocator; 530571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com} 531571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 5323aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comSkPdfNativeObject* SkPdfNativeDoc::resolveReference(SkPdfNativeObject* ref) { 533571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (ref && ref->isReference()) { 534571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com int id = ref->referenceId(); 535571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com // TODO(edisonn): generation/updates not supported now 536571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com //int gen = ref->referenceGeneration(); 537571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 538641cce90c99f17e7c4d3d6407c3c4bbf591c5a3fedisonn@google.com // TODO(edisonn): verify id and gen expected 539641cce90c99f17e7c4d3d6407c3c4bbf591c5a3fedisonn@google.com if (id < 0 || id >= fObjects.count()) { 540c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReport(kIgnoreError_SkPdfIssueSeverity, kReadStreamError_SkPdfIssue, 541c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com "resolve reference id out of bounds", NULL, NULL); 542571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return NULL; 543571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 544571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 545f68aed33819cbc98a95edeadde1da9303eca7fb2edisonn@google.com if (fObjects[id].fIsReferenceResolved) { 546c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com SkPdfReportIf(!fObjects[id].fResolvedReference, kIgnoreError_SkPdfIssueSeverity, 547c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com kBadReference_SkPdfIssue, "ref is NULL", NULL, NULL); 548571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return fObjects[id].fResolvedReference; 549571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 550571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 551c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // TODO(edisonn): there are pdfs in the crashing suite that cause a stack overflow 552c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // here unless we check for resolved reference on next line. 553c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // Determine if the pdf is corrupted, or we have a bug here. 554f68aed33819cbc98a95edeadde1da9303eca7fb2edisonn@google.com 555c8fda9d96be0bd944d37a6e23f7adad5f247c51dedisonn@google.com // Avoids recursive calls 556f68aed33819cbc98a95edeadde1da9303eca7fb2edisonn@google.com fObjects[id].fIsReferenceResolved = true; 557f68aed33819cbc98a95edeadde1da9303eca7fb2edisonn@google.com 558571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (fObjects[id].fObj == NULL) { 559571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com fObjects[id].fObj = readObject(id); 560571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 561571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 562608c35e5c4ce61a79b7a0567c8eca569332c2ddeedisonn@google.com if (fObjects[id].fObj != NULL && fObjects[id].fResolvedReference == NULL) { 563571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com if (!fObjects[id].fObj->isReference()) { 564571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com fObjects[id].fResolvedReference = fObjects[id].fObj; 565571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } else { 566571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com fObjects[id].fResolvedReference = resolveReference(fObjects[id].fObj); 567571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 568571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 569571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com 570571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com return fObjects[id].fResolvedReference; 571571c70b95f56e22b5a7d6f4f288aa6c9a925a64fedisonn@google.com } 572276fed9e0ae2e4457efd61eeb14738040feb65f1edisonn@google.com 5733aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.com return (SkPdfNativeObject*)ref; 5743aac1f9f308192f3787265830fe86ce8874e7382edisonn@google.com} 575a5aaa7998fc18489701660f781d7daa33ffc6f6eedisonn@google.com 5763aa355527a3b91d3e12b8bee49e5637d00a736caedisonn@google.comsize_t SkPdfNativeDoc::bytesUsed() const { 577a5aaa7998fc18489701660f781d7daa33ffc6f6eedisonn@google.com return fAllocator->bytesUsed() + 578a5aaa7998fc18489701660f781d7daa33ffc6f6eedisonn@google.com fContentLength + 579a5aaa7998fc18489701660f781d7daa33ffc6f6eedisonn@google.com fObjects.count() * sizeof(PublicObjectEntry) + 580a5aaa7998fc18489701660f781d7daa33ffc6f6eedisonn@google.com fPages.count() * sizeof(SkPdfPageObjectDictionary*) + 581a5aaa7998fc18489701660f781d7daa33ffc6f6eedisonn@google.com sizeof(*this); 582a5aaa7998fc18489701660f781d7daa33ffc6f6eedisonn@google.com} 583