pdfviewer: more load references dinamically plumming

Review URL: https://codereview.chromium.org/18536014

git-svn-id: http://skia.googlecode.com/svn/trunk@9988 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/PdfViewer/generate_code.py b/experimental/PdfViewer/generate_code.py
index 51fa173..c106bbc 100644
--- a/experimental/PdfViewer/generate_code.py
+++ b/experimental/PdfViewer/generate_code.py
@@ -374,8 +374,8 @@
           if len(prop.fTypes.split()) == 1:
             t = prop.fTypes.strip()
 
-            nativeFileClass.write('  ' + knowTypes[t][0] + ' ' + prop.fCppName + '(const SkNativeParsedPDF* doc);\n')
-            nativeFileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::' + prop.fCppName + '(const SkNativeParsedPDF* doc) {\n')
+            nativeFileClass.write('  ' + knowTypes[t][0] + ' ' + prop.fCppName + '(SkNativeParsedPDF* doc);\n')
+            nativeFileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::' + prop.fCppName + '(SkNativeParsedPDF* doc) {\n')
             nativeFileClassCpp.write('  SkPdfObject* ret = get(\"' + prop.fName + '\", \"' + prop.fAbr + '\");\n')
             nativeFileClassCpp.write('  if (doc) {ret = doc->resolveReference(ret);}\n')
             nativeFileClassCpp.write('  if ((ret != NULL && ' + knowTypes[t][3] + ') || (doc == NULL && ret != NULL && ret->isReference())) return ' + knowTypes[t][1] + ';\n')
@@ -395,17 +395,17 @@
             for type in prop.fTypes.split():
               t = type.strip()
               
-              nativeFileClass.write('  bool is' + prop.fCppName + 'A' + t.title() + '(const SkNativeParsedPDF* doc);\n')
+              nativeFileClass.write('  bool is' + prop.fCppName + 'A' + t.title() + '(SkNativeParsedPDF* doc);\n')
 
-              nativeFileClassCpp.write('bool SkPdf' + cls.fName + '::is' + prop.fCppName + 'A' + t.title() + '(const SkNativeParsedPDF* doc) {\n')
+              nativeFileClassCpp.write('bool SkPdf' + cls.fName + '::is' + prop.fCppName + 'A' + t.title() + '(SkNativeParsedPDF* doc) {\n')
               nativeFileClassCpp.write('  SkPdfObject* ret = get(\"' + prop.fName + '\", \"' + prop.fAbr + '\");\n')
               nativeFileClassCpp.write('  if (doc) {ret = doc->resolveReference(ret);}\n')
               nativeFileClassCpp.write('  return ret != NULL && ' + knowTypes[t][3] + ';\n')
               nativeFileClassCpp.write('}\n')
               nativeFileClassCpp.write('\n')
 
-              nativeFileClass.write('  ' + knowTypes[t][0] + ' get' + prop.fCppName + 'As' + t.title() + '(const SkNativeParsedPDF* doc);\n')
-              nativeFileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::get' + prop.fCppName + 'As' + t.title() + '(const SkNativeParsedPDF* doc) {\n')
+              nativeFileClass.write('  ' + knowTypes[t][0] + ' get' + prop.fCppName + 'As' + t.title() + '(SkNativeParsedPDF* doc);\n')
+              nativeFileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::get' + prop.fCppName + 'As' + t.title() + '(SkNativeParsedPDF* doc) {\n')
 
               nativeFileClassCpp.write('  SkPdfObject* ret = get(\"' + prop.fName + '\", \"' + prop.fAbr + '\");\n')
               nativeFileClassCpp.write('  if (doc) {ret = doc->resolveReference(ret);}\n')
@@ -468,11 +468,11 @@
     
     fileMapperNative.write('class SkPdfMapper {\n')
 
-    fileMapperNative.write('  const SkNativeParsedPDF* fParsedDoc;\n')
+    fileMapperNative.write('  SkNativeParsedPDF* fParsedDoc;\n')
     
     fileMapperNative.write('public:\n')
     
-    fileMapperNative.write('  SkPdfMapper(const SkNativeParsedPDF* doc) : fParsedDoc(doc) {}\n')
+    fileMapperNative.write('  SkPdfMapper(SkNativeParsedPDF* doc) : fParsedDoc(doc) {}\n')
     fileMapperNative.write('\n')
     
     for name in self.fClassesNamesInOrder:
diff --git a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp
index 9b668da..7a8ba6f 100644
--- a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp
@@ -128,14 +128,14 @@
     while (current < trailerEnd) {
         token.reset();
         unsigned char* previous = current;
-        current = nextObject(current, trailerEnd, &token, NULL);
+        current = nextObject(current, trailerEnd, &token, NULL, NULL);
         if (!token.isInteger()) {
             return previous;
         }
 
         int startId = (int)token.intValue();
         token.reset();
-        current = nextObject(current, trailerEnd, &token, NULL);
+        current = nextObject(current, trailerEnd, &token, NULL, NULL);
 
         if (!token.isInteger()) {
             // TODO(edisonn): report/warning
@@ -146,7 +146,7 @@
 
         for (int i = 0; i < entries; i++) {
             token.reset();
-            current = nextObject(current, trailerEnd, &token, NULL);
+            current = nextObject(current, trailerEnd, &token, NULL, NULL);
             if (!token.isInteger()) {
                 // TODO(edisonn): report/warning
                 return current;
@@ -154,7 +154,7 @@
             int offset = (int)token.intValue();
 
             token.reset();
-            current = nextObject(current, trailerEnd, &token, NULL);
+            current = nextObject(current, trailerEnd, &token, NULL, NULL);
             if (!token.isInteger()) {
                 // TODO(edisonn): report/warning
                 return current;
@@ -162,7 +162,7 @@
             int generation = (int)token.intValue();
 
             token.reset();
-            current = nextObject(current, trailerEnd, &token, NULL);
+            current = nextObject(current, trailerEnd, &token, NULL, NULL);
             if (!token.isKeyword() || token.len() != 1 || (*token.c_str() != 'f' && *token.c_str() != 'n')) {
                 // TODO(edisonn): report/warning
                 return current;
@@ -179,7 +179,7 @@
     unsigned char* current = ignoreLine(trailerStart, trailerEnd);  // TODO(edisonn): verify next keyord is "trailer" use nextObject here
 
     SkPdfObject token;
-    current = nextObject(current, trailerEnd, &token, fAllocator);
+    current = nextObject(current, trailerEnd, &token, fAllocator, NULL);
     if (!token.isDictionary()) {
         return -1;
     }
@@ -214,7 +214,7 @@
     fObjects[id].fObj = NULL;
 }
 
-SkPdfObject* SkNativeParsedPDF::readObject(int id/*, int expectedGeneration*/) const {
+SkPdfObject* SkNativeParsedPDF::readObject(int id/*, int expectedGeneration*/) {
     long startOffset = fObjects[id].fOffset;
     //long endOffset = fObjects[id].fOffsetEnd;
     // TODO(edisonn): use hinted endOffset
@@ -225,26 +225,26 @@
     unsigned char* current = fFileContent + startOffset;
     unsigned char* end = fFileContent + fContentLength;
 
-    SkPdfNativeTokenizer tokenizer(current, end - current, fMapper, fAllocator);
+    SkPdfNativeTokenizer tokenizer(current, end - current, fMapper, fAllocator, this);
 
     SkPdfObject idObj;
     SkPdfObject generationObj;
     SkPdfObject objKeyword;
     SkPdfObject* dict = fAllocator->allocObject();
 
-    current = nextObject(current, end, &idObj, NULL);
+    current = nextObject(current, end, &idObj, NULL, NULL);
     if (current >= end) {
         // TODO(edisonn): report warning/error
         return NULL;
     }
 
-    current = nextObject(current, end, &generationObj, NULL);
+    current = nextObject(current, end, &generationObj, NULL, NULL);
     if (current >= end) {
         // TODO(edisonn): report warning/error
         return NULL;
     }
 
-    current = nextObject(current, end, &objKeyword, NULL);
+    current = nextObject(current, end, &objKeyword, NULL, NULL);
     if (current >= end) {
         // TODO(edisonn): report warning/error
         return NULL;
@@ -258,7 +258,7 @@
         // TODO(edisonn): report warning/error
     }
 
-    current = nextObject(current, end, dict, fAllocator);
+    current = nextObject(current, end, dict, fAllocator, this);
 
     // TODO(edisonn): report warning/error - verify last token is endobj
 
@@ -293,7 +293,7 @@
 }
 
 // TODO(edisonn): Partial implemented. Move the logics directly in the code generator for inheritable and default value?
-SkRect SkNativeParsedPDF::MediaBox(int page) const {
+SkRect SkNativeParsedPDF::MediaBox(int page) {
     SkPdfPageObjectDictionary* current = fPages[page];
     while (!current->has_MediaBox() && current->has_Parent()) {
         current = (SkPdfPageObjectDictionary*)current->Parent(this);
@@ -305,7 +305,7 @@
 }
 
 // TODO(edisonn): stream or array ... ? for now only array
-SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfPage(int page) const {
+SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfPage(int page) {
     if (fPages[page]->isContentsAStream(this)) {
         return tokenizerOfStream(fPages[page]->getContentsAsStream(this));
     } else {
@@ -315,19 +315,19 @@
     }
 }
 
-SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfStream(SkPdfObject* stream) const {
+SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfStream(SkPdfObject* stream) {
     if (stream == NULL) {
         return NULL;
     }
 
-    return new SkPdfNativeTokenizer(stream, fMapper, fAllocator);
+    return new SkPdfNativeTokenizer(stream, fMapper, fAllocator, this);
 }
 
 // TODO(edisonn): NYI
-SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfBuffer(unsigned char* buffer, size_t len) const {
+SkPdfNativeTokenizer* SkNativeParsedPDF::tokenizerOfBuffer(unsigned char* buffer, size_t len) {
     // warning does not track two calls in the same buffer! the buffer is updated!
     // make a clean copy if needed!
-    return new SkPdfNativeTokenizer(buffer, len, fMapper, fAllocator);
+    return new SkPdfNativeTokenizer(buffer, len, fMapper, fAllocator, this);
 }
 
 size_t SkNativeParsedPDF::objects() const {
@@ -376,13 +376,9 @@
     return fAllocator;
 }
 
-SkPdfObject* SkNativeParsedPDF::resolveReference(SkPdfObject* ref) const {
-    return (SkPdfObject*)resolveReference((const SkPdfObject*)ref);
-}
-
 // TODO(edisonn): fix infinite loop if ref to itself!
 // TODO(edisonn): perf, fix refs at load, and resolve will simply return fResolvedReference?
-SkPdfObject* SkNativeParsedPDF::resolveReference(const SkPdfObject* ref) const {
+SkPdfObject* SkNativeParsedPDF::resolveReference(const SkPdfObject* ref) {
     if (ref && ref->isReference()) {
         int id = ref->referenceId();
         // TODO(edisonn): generation/updates not supported now
diff --git a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h
index 245bdfb..f61114b 100644
--- a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h
+++ b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h
@@ -42,11 +42,11 @@
 
     int pages() const;
     SkPdfResourceDictionary* pageResources(int page);
-    SkRect MediaBox(int page) const;
-    SkPdfNativeTokenizer* tokenizerOfPage(int n) const;
+    SkRect MediaBox(int page);
+    SkPdfNativeTokenizer* tokenizerOfPage(int n);
 
-    SkPdfNativeTokenizer* tokenizerOfStream(SkPdfObject* stream) const;
-    SkPdfNativeTokenizer* tokenizerOfBuffer(unsigned char* buffer, size_t len) const;
+    SkPdfNativeTokenizer* tokenizerOfStream(SkPdfObject* stream);
+    SkPdfNativeTokenizer* tokenizerOfBuffer(unsigned char* buffer, size_t len);
 
     size_t objects() const;
     SkPdfObject* object(int i);
@@ -61,8 +61,7 @@
 
     void drawPage(int page, SkCanvas* canvas);
 
-    SkPdfObject* resolveReference(SkPdfObject* ref) const;
-    SkPdfObject* resolveReference(const SkPdfObject* ref) const;
+    SkPdfObject* resolveReference(const SkPdfObject* ref);
 
 private:
 
@@ -77,7 +76,7 @@
         obj->fOffset = -1;
     }
 
-    SkPdfObject* readObject(int id/*, int generation*/) const;
+    SkPdfObject* readObject(int id/*, int generation*/);
 
     void fillPages(SkPdfPageTreeNodeDictionary* tree);
 
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
index fc3e0b9..1288132 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
@@ -40,7 +40,7 @@
 }
 
 // last elem has to be ]
-static unsigned char* readArray(unsigned char* start, unsigned char* end, SkPdfObject* array, SkPdfAllocator* allocator) {
+static unsigned char* readArray(unsigned char* start, unsigned char* end, SkPdfObject* array, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) {
     while (start < end) {
         // skip white spaces
         start = skipPdfWhiteSpaces(start, end);
@@ -57,7 +57,7 @@
         }
 
         SkPdfObject* newObj = allocator->allocObject();
-        start = nextObject(start, end, newObj, allocator);
+        start = nextObject(start, end, newObj, allocator, doc);
         // TODO(edisonn): perf/memory: put the variables on the stack, and flush them on the array only when
         // we are sure they are not references!
         if (newObj->isKeywordReference() && array->size() >= 2 && array->objAtAIndex(array->size() - 1)->isInteger() && array->objAtAIndex(array->size() - 2)->isInteger()) {
@@ -443,7 +443,7 @@
 // right now implement the silly algorithm that assumes endstream is finishing the stream
 
 
-static unsigned char* readStream(unsigned char* start, unsigned char* end, SkPdfObject* dict) {
+static unsigned char* readStream(unsigned char* start, unsigned char* end, SkPdfObject* dict, SkNativeParsedPDF* doc) {
     start = skipPdfWhiteSpaces(start, end);
     if (!(start[0] == 's' && start[1] == 't' && start[2] == 'r' && start[3] == 'e' && start[4] == 'a' && start[5] == 'm')) {
         // no stream. return.
@@ -462,8 +462,8 @@
     int64_t length = -1;
 
     // TODO(edisonn): very basic implementation
-    if (stream->has_Length() && stream->Length(NULL) > 0) {
-        length = stream->Length(NULL);
+    if (stream->has_Length() && stream->Length(doc) > 0) {
+        length = stream->Length(doc);
     }
 
     // TODO(edisonn): laod external streams
@@ -504,7 +504,7 @@
     return start;
 }
 
-static unsigned char* readDictionary(unsigned char* start, unsigned char* end, SkPdfObject* dict, SkPdfAllocator* allocator) {
+static unsigned char* readDictionary(unsigned char* start, unsigned char* end, SkPdfObject* dict, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) {
     SkPdfObject::makeEmptyDictionary(dict);
 
     start = skipPdfWhiteSpaces(start, end);
@@ -518,7 +518,7 @@
 
         if (start < end) {
             SkPdfObject* value = allocator->allocObject();
-            start = nextObject(start, end, value, allocator);
+            start = nextObject(start, end, value, allocator, doc);
 
             start = skipPdfWhiteSpaces(start, end);
 
@@ -526,10 +526,10 @@
                 // seems we have an indirect reference
                 if (isPdfDigit(*start)) {
                     SkPdfObject generation;
-                    start = nextObject(start, end, &generation, allocator);
+                    start = nextObject(start, end, &generation, allocator, doc);
 
                     SkPdfObject keywordR;
-                    start = nextObject(start, end, &keywordR, allocator);
+                    start = nextObject(start, end, &keywordR, allocator, doc);
 
                     if (value->isInteger() && generation.isInteger() && keywordR.isKeywordReference()) {
                         int64_t id = value->intValue();
@@ -566,12 +566,12 @@
     // TODO(edisonn): read stream ... put dict and stream in a struct, and have a pointer to struct ...
     // or alocate 2 objects, and if there is no stream, free it to be used by someone else? or just leave it ?
 
-    start = readStream(start, end, dict);
+    start = readStream(start, end, dict, doc);
 
     return start;
 }
 
-unsigned char* nextObject(unsigned char* start, unsigned char* end, SkPdfObject* token, SkPdfAllocator* allocator) {
+unsigned char* nextObject(unsigned char* start, unsigned char* end, SkPdfObject* token, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) {
     unsigned char* current;
 
     // skip white spaces
@@ -592,7 +592,7 @@
             case kOpenedSquareBracket_PdfDelimiter:
                 *start = '\0';
                 SkPdfObject::makeEmptyArray(token);
-                return readArray(current, end, token, allocator);
+                return readArray(current, end, token, allocator, doc);
 
             case kOpenedRoundBracket_PdfDelimiter:
                 *start = '\0';
@@ -602,7 +602,7 @@
                 *start = '\0';
                 if (end > start + 1 && start[1] == kOpenedInequityBracket_PdfDelimiter) {
                     // TODO(edisonn): pass here the length somehow?
-                    return readDictionary(start + 2, end, token, allocator);  // skip <<
+                    return readDictionary(start + 2, end, token, allocator, doc);  // skip <<
                 } else {
                     return readHexString(start + 1, end, token);  // skip <
                 }
@@ -678,7 +678,7 @@
 }
 
 // TODO(edisonn): perf: do no copy the buffers, but use them, and mark cache the result, so there is no need of a second pass
-SkPdfNativeTokenizer::SkPdfNativeTokenizer(SkPdfObject* objWithStream, const SkPdfMapper* mapper, SkPdfAllocator* allocator) : fMapper(mapper), fAllocator(allocator), fUncompressedStream(NULL), fUncompressedStreamEnd(NULL), fEmpty(false), fHasPutBack(false) {
+SkPdfNativeTokenizer::SkPdfNativeTokenizer(SkPdfObject* objWithStream, const SkPdfMapper* mapper, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) : fDoc(doc), fMapper(mapper), fAllocator(allocator), fUncompressedStream(NULL), fUncompressedStreamEnd(NULL), fEmpty(false), fHasPutBack(false) {
     unsigned char* buffer = NULL;
     size_t len = 0;
     objWithStream->GetFilteredStreamRef(&buffer, &len, fAllocator);
@@ -692,7 +692,7 @@
     memcpy(fUncompressedStream, buffer, len);
 }
 
-SkPdfNativeTokenizer::SkPdfNativeTokenizer(unsigned char* buffer, int len, const SkPdfMapper* mapper, SkPdfAllocator* allocator) : fMapper(mapper), fAllocator(allocator), fEmpty(false), fHasPutBack(false) {
+SkPdfNativeTokenizer::SkPdfNativeTokenizer(unsigned char* buffer, int len, const SkPdfMapper* mapper, SkPdfAllocator* allocator, SkNativeParsedPDF* doc) : fDoc(doc), fMapper(mapper), fAllocator(allocator), fEmpty(false), fHasPutBack(false) {
     // TODO(edisonn): hack, find end of object
     char* endobj = strstr((char*)buffer, "endobj");
     if (endobj) {
@@ -716,7 +716,7 @@
     }
 
     SkPdfObject obj;
-    fUncompressedStream = nextObject(fUncompressedStream, fUncompressedStreamEnd, &obj, fAllocator);
+    fUncompressedStream = nextObject(fUncompressedStream, fUncompressedStreamEnd, &obj, fAllocator, fDoc);
 
     // If it is a keyword, we will only get the pointer of the string
     if (obj.type() == SkPdfObject::kKeyword_PdfObjectType) {
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h
index 1c2336e..333d9dc 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h
@@ -102,7 +102,8 @@
     }
 };
 
-unsigned char* nextObject(unsigned char* start, unsigned char* end, SkPdfObject* token, SkPdfAllocator* allocator);
+class SkNativeParsedPDF;
+unsigned char* nextObject(unsigned char* start, unsigned char* end, SkPdfObject* token, SkPdfAllocator* allocator, SkNativeParsedPDF* doc);
 
 enum SkPdfTokenType {
     kKeyword_TokenType,
@@ -120,8 +121,8 @@
 
 class SkPdfNativeTokenizer {
 public:
-    SkPdfNativeTokenizer(SkPdfObject* objWithStream, const SkPdfMapper* mapper, SkPdfAllocator* allocator);
-    SkPdfNativeTokenizer(unsigned char* buffer, int len, const SkPdfMapper* mapper, SkPdfAllocator* allocator);
+    SkPdfNativeTokenizer(SkPdfObject* objWithStream, const SkPdfMapper* mapper, SkPdfAllocator* allocator, SkNativeParsedPDF* doc);
+    SkPdfNativeTokenizer(unsigned char* buffer, int len, const SkPdfMapper* mapper, SkPdfAllocator* allocator, SkNativeParsedPDF* doc);
 
     virtual ~SkPdfNativeTokenizer();
 
@@ -130,6 +131,7 @@
     void PutBack(PdfToken token);
 
 private:
+    SkNativeParsedPDF* fDoc;
     const SkPdfMapper* fMapper;
     SkPdfAllocator* fAllocator;