pdfviewer: (part 1) store the offset of the location of object in file/stream. In order to use the feature, enable the macro defined in SkPdfConfig.h

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

git-svn-id: http://skia.googlecode.com/svn/trunk@11117 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/PdfViewer/SkPdfConfig.h b/experimental/PdfViewer/SkPdfConfig.h
index b4f5298..905041b 100644
--- a/experimental/PdfViewer/SkPdfConfig.h
+++ b/experimental/PdfViewer/SkPdfConfig.h
@@ -8,7 +8,7 @@
 #ifndef SkPdfConfig_DEFINED
 #define SkPdfConfig_DEFINED
 
-#define PDF_TRACK_OBJECT_USAGE
+//#define PDF_TRACK_OBJECT_USAGE
 //#define PDF_TRACK_STREAM_OFFSETS
 //#define PDF_TRACE
 //#define PDF_TRACE_READ_TOKEN
@@ -33,4 +33,45 @@
 #define SkPdfMarkObjectUnused()
 #endif   // PDF_TRACK_OBJECT_USAGE
 
+#ifdef PDF_TRACK_STREAM_OFFSETS
+
+// TODO(edisonn): track source files
+#define SkPdfTrackSrourceFile(foo) -2
+
+#define GET_TRACK_STREAM , int streamId, const unsigned char* streamStart
+#define PUT_TRACK_STREAM_ARGS , streamId, streamStart
+#define PUT_TRACK_STREAM(start,end) , streamId, start-streamStart, end-streamStart
+#define PUT_TRACK_STREAM_ARGS_EXPL(a,b,c) , a, b, c
+#define PUT_TRACK_STREAM_ARGS_EXPL2(a,b) , a, b
+
+
+#define PUT_TRACK_PARAMETERS , streamId, offsetStart, offsetEnd
+#define PUT_TRACK_PARAMETERS_OBJ(obj) , (obj)->streamId(), (obj)->offsetStart(), (obj)->offsetEnd()
+#define PUT_TRACK_PARAMETERS_OBJ2(obj,objEnd) , (obj)->streamId(), (obj)->offsetStart(), (objEnd)->offsetEnd()
+#define PUT_TRACK_PARAMETERS_SRC , SkPdfTrackSrourceFile(__FILE__), __LINE__, __LINE__
+#define PUT_TRACK_PARAMETERS_SRC0  SkPdfTrackSrourceFile(__FILE__), __LINE__, __LINE__
+#define GET_TRACK_PARAMETERS , int streamId, int offsetStart, int offsetEnd
+#define GET_TRACK_PARAMETERS0  int streamId, int offsetStart, int offsetEnd
+#define STORE_TRACK_PARAMETERS(obj) (obj)->fStreamId = streamId; (obj)->fOffsetStart = offsetStart; (obj)->fOffsetEnd = offsetEnd;
+#define STORE_TRACK_PARAMETER_OFFSET_END(obj,offsetEnd) (obj)->fOffsetEnd = (offsetEnd)-streamStart;
+#else
+#define GET_TRACK_STREAM
+#define PUT_TRACK_STREAM_ARGS
+#define PUT_TRACK_STREAM(start,end)
+#define PUT_TRACK_STREAM_ARGS_EXPL(a,b,c)
+#define PUT_TRACK_STREAM_ARGS_EXPL2(a,b)
+
+
+#define PUT_TRACK_PARAMETERS
+#define PUT_TRACK_PARAMETERS_OBJ(obj)
+#define PUT_TRACK_PARAMETERS_OBJ2(obj,objEnd)
+#define PUT_TRACK_PARAMETERS_SRC
+#define PUT_TRACK_PARAMETERS_SRC0
+#define GET_TRACK_PARAMETERS
+#define GET_TRACK_PARAMETERS0
+#define STORE_TRACK_PARAMETERS(obj)
+#define STORE_TRACK_PARAMETER_OFFSET_END(obj,offsetEnd)
+#endif   //PDF_TRACK_STREAM_OFFSETS
+
+
 #endif  // SkPdfConfig_DEFINED
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp
index ebc27ad..f278ea1 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp
@@ -177,16 +177,16 @@
     current = skipPdfWhiteSpaces(0, current, end);
     while (current < end) {
         SkPdfNativeObject token;
-        current = nextObject(0, current, end, &token, NULL, NULL);
+        current = nextObject(0, current, end, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
         if (token.isInteger()) {
             int id = (int)token.intValue();
 
             token.reset();
-            current = nextObject(0, current, end, &token, NULL, NULL);
+            current = nextObject(0, current, end, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
             // int generation = (int)token.intValue();  // TODO(edisonn): ignored for now
 
             token.reset();
-            current = nextObject(0, current, end, &token, NULL, NULL);
+            current = nextObject(0, current, end, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
             // TODO(edisonn): must be obj, return error if not? ignore ?
             if (!token.isKeyword("obj")) {
                 continue;
@@ -199,7 +199,7 @@
             fObjects[id].fOffset = current - fFileContent;
 
             SkPdfNativeObject* obj = fAllocator->allocObject();
-            current = nextObject(0, current, end, obj, fAllocator, this);
+            current = nextObject(0, current, end, obj, fAllocator, this PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
 
             fObjects[id].fResolvedReference = obj;
             fObjects[id].fObj = obj;
@@ -210,7 +210,7 @@
             current = readTrailer(current, end, true, &dummy, true);
         } else if (token.isKeyword("startxref")) {
             token.reset();
-            current = nextObject(0, current, end, &token, NULL, NULL);  // ignore
+            current = nextObject(0, current, end, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));  // ignore
         }
 
         current = skipPdfWhiteSpaces(0, current, end);
@@ -249,7 +249,7 @@
 
 const unsigned char* SkPdfNativeDoc::readCrossReferenceSection(const unsigned char* xrefStart, const unsigned char* trailerEnd) {
     SkPdfNativeObject xref;
-    const unsigned char* current = nextObject(0, xrefStart, trailerEnd, &xref, NULL, NULL);
+    const unsigned char* current = nextObject(0, xrefStart, trailerEnd, &xref, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
 
     if (!xref.isKeyword("xref")) {
         return trailerEnd;
@@ -259,14 +259,14 @@
     while (current < trailerEnd) {
         token.reset();
         const unsigned char* previous = current;
-        current = nextObject(0, current, trailerEnd, &token, NULL, NULL);
+        current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
         if (!token.isInteger()) {
             return previous;
         }
 
         int startId = (int)token.intValue();
         token.reset();
-        current = nextObject(0, current, trailerEnd, &token, NULL, NULL);
+        current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
 
         if (!token.isInteger()) {
             // TODO(edisonn): report/warning
@@ -277,7 +277,7 @@
 
         for (int i = 0; i < entries; i++) {
             token.reset();
-            current = nextObject(0, current, trailerEnd, &token, NULL, NULL);
+            current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
             if (!token.isInteger()) {
                 // TODO(edisonn): report/warning
                 return current;
@@ -285,7 +285,7 @@
             int offset = (int)token.intValue();
 
             token.reset();
-            current = nextObject(0, current, trailerEnd, &token, NULL, NULL);
+            current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
             if (!token.isInteger()) {
                 // TODO(edisonn): report/warning
                 return current;
@@ -293,7 +293,7 @@
             int generation = (int)token.intValue();
 
             token.reset();
-            current = nextObject(0, current, trailerEnd, &token, NULL, NULL);
+            current = nextObject(0, current, trailerEnd, &token, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
             if (!token.isKeyword() || token.lenstr() != 1 || (*token.c_str() != 'f' && *token.c_str() != 'n')) {
                 // TODO(edisonn): report/warning
                 return current;
@@ -314,7 +314,7 @@
         SkPdfNativeObject 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);
+        current = nextObject(0, current, trailerEnd, &trailerKeyword, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
 
         if (!trailerKeyword.isKeyword() || strlen("trailer") != trailerKeyword.lenstr() ||
             strncmp(trailerKeyword.c_str(), "trailer", strlen("trailer")) != 0) {
@@ -324,7 +324,7 @@
     }
 
     SkPdfNativeObject token;
-    current = nextObject(0, current, trailerEnd, &token, fAllocator, NULL);
+    current = nextObject(0, current, trailerEnd, &token, fAllocator, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
     if (!token.isDictionary()) {
         return current;
     }
@@ -379,19 +379,19 @@
     SkPdfNativeObject objKeyword;
     SkPdfNativeObject* dict = fAllocator->allocObject();
 
-    current = nextObject(0, current, end, &idObj, NULL, NULL);
+    current = nextObject(0, current, end, &idObj, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
     if (current >= end) {
         // TODO(edisonn): report warning/error
         return NULL;
     }
 
-    current = nextObject(0, current, end, &generationObj, NULL, NULL);
+    current = nextObject(0, current, end, &generationObj, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
     if (current >= end) {
         // TODO(edisonn): report warning/error
         return NULL;
     }
 
-    current = nextObject(0, current, end, &objKeyword, NULL, NULL);
+    current = nextObject(0, current, end, &objKeyword, NULL, NULL PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
     if (current >= end) {
         // TODO(edisonn): report warning/error
         return NULL;
@@ -405,7 +405,7 @@
         // TODO(edisonn): report warning/error
     }
 
-    current = nextObject(1, current, end, dict, fAllocator, this);
+    current = nextObject(1, current, end, dict, fAllocator, this PUT_TRACK_STREAM_ARGS_EXPL2(0, fFileContent));
 
     // TODO(edisonn): report warning/error - verify last token is endobj
 
@@ -513,19 +513,19 @@
 
 SkPdfReal* SkPdfNativeDoc::createReal(double value) const {
     SkPdfNativeObject* obj = fAllocator->allocObject();
-    SkPdfNativeObject::makeReal(value, obj);
+    SkPdfNativeObject::makeReal(value, obj PUT_TRACK_PARAMETERS_SRC);
     return (SkPdfReal*)obj;
 }
 
 SkPdfInteger* SkPdfNativeDoc::createInteger(int value) const {
     SkPdfNativeObject* obj = fAllocator->allocObject();
-    SkPdfNativeObject::makeInteger(value, obj);
+    SkPdfNativeObject::makeInteger(value, obj PUT_TRACK_PARAMETERS_SRC);
     return (SkPdfInteger*)obj;
 }
 
 SkPdfString* SkPdfNativeDoc::createString(const unsigned char* sz, size_t len) const {
     SkPdfNativeObject* obj = fAllocator->allocObject();
-    SkPdfNativeObject::makeString(sz, len, obj);
+    SkPdfNativeObject::makeString(sz, len, obj PUT_TRACK_PARAMETERS_SRC);
     return (SkPdfString*)obj;
 }
 
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp
index 9411368..54daf17 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.cpp
@@ -18,7 +18,7 @@
 #include "SkBitmap.h"
 #include "SkPdfFont.h"
 
-SkPdfNativeObject SkPdfNativeObject::kNull = SkPdfNativeObject::makeNull();
+SkPdfNativeObject SkPdfNativeObject::kNull = SkPdfNativeObject::makeNull(PUT_TRACK_PARAMETERS_SRC0);
 
 bool SkPdfNativeObject::applyFlateDecodeFilter() {
     if (!SkFlate::HaveFlate()) {
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h b/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h
index f26b53b..344d6c6 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeObject.h
@@ -103,12 +103,26 @@
     DataType fDataType;
 
 
-    // Keep this the last entrys
+    // Keep this the last entries
 #ifdef PDF_TRACK_OBJECT_USAGE
     mutable bool fUsed;
 #endif   // PDF_TRACK_OBJECT_USAGE
 
+#ifdef PDF_TRACK_STREAM_OFFSETS
 public:
+    int fStreamId;
+    int fOffsetStart;
+    int fOffsetEnd;
+#endif  // PDF_TRACK_STREAM_OFFSETS
+
+public:
+
+#ifdef PDF_TRACK_STREAM_OFFSETS
+    int streamId() const { return fStreamId; }
+    int offsetStart() const { return fOffsetStart; }
+    int offsetEnd() const { return fOffsetEnd; }
+#endif  // PDF_TRACK_STREAM_OFFSETS
+
 
     SkPdfNativeObject() : fInRendering(0)
                         , fObjectType(kInvalid_PdfObjectType)
@@ -118,6 +132,12 @@
 #ifdef PDF_TRACK_OBJECT_USAGE
                         , fUsed(false)
 #endif   // PDF_TRACK_OBJECT_USAGE
+
+#ifdef PDF_TRACK_STREAM_OFFSETS
+                        , fStreamId(-1)
+                        , fOffsetStart(-1)
+                        , fOffsetEnd(-1)
+#endif  // PDF_TRACK_STREAM_OFFSETS
     {}
 
     bool inRendering() const { return fInRendering != 0; }
@@ -231,49 +251,63 @@
         return nyi;
     }
 
-    static void makeBoolean(bool value, SkPdfNativeObject* obj) {
+    static void makeBoolean(bool value, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        STORE_TRACK_PARAMETERS(obj);
+
         SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
 
         obj->fObjectType = kBoolean_PdfObjectType;
         obj->fBooleanValue = value;
     }
 
-    static SkPdfNativeObject makeBoolean(bool value) {
+    static SkPdfNativeObject makeBoolean(bool value GET_TRACK_PARAMETERS) {
         SkPdfNativeObject obj;
+
+        STORE_TRACK_PARAMETERS(&obj);
+
         obj.fObjectType = kBoolean_PdfObjectType;
         obj.fBooleanValue = value;
         return obj;
     }
 
-    static void makeInteger(int64_t value, SkPdfNativeObject* obj) {
+    static void makeInteger(int64_t value, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        STORE_TRACK_PARAMETERS(obj);
+
         SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
 
         obj->fObjectType = kInteger_PdfObjectType;
         obj->fIntegerValue = value;
     }
 
-    static void makeReal(double value, SkPdfNativeObject* obj) {
+    static void makeReal(double value, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        STORE_TRACK_PARAMETERS(obj);
+
         SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
 
         obj->fObjectType = kReal_PdfObjectType;
         obj->fRealValue = value;
     }
 
-    static void makeNull(SkPdfNativeObject* obj) {
+    static void makeNull(SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        STORE_TRACK_PARAMETERS(obj);
+
         SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
 
         obj->fObjectType = kNull_PdfObjectType;
     }
 
-    static SkPdfNativeObject makeNull() {
+    static SkPdfNativeObject makeNull(GET_TRACK_PARAMETERS0) {
         SkPdfNativeObject obj;
+
+        STORE_TRACK_PARAMETERS(&obj);
+
         obj.fObjectType = kNull_PdfObjectType;
         return obj;
     }
 
     static SkPdfNativeObject kNull;
 
-    static void makeNumeric(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
+    static void makeNumeric(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
         SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
 
         // TODO(edisonn): NYI properly
@@ -287,13 +321,15 @@
             // TODO(edisonn): report parse issue with numbers like "24asdasd123"
         }
         if (isInt) {
-            makeInteger(atol((const char*)start), obj);
+            makeInteger(atol((const char*)start), obj PUT_TRACK_PARAMETERS);
         } else {
-            makeReal(atof((const char*)start), obj);
+            makeReal(atof((const char*)start), obj PUT_TRACK_PARAMETERS);
         }
     }
 
-    static void makeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj) {
+    static void makeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        STORE_TRACK_PARAMETERS(obj);
+
         SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
 
         obj->fObjectType = kReference_PdfObjectType;
@@ -301,62 +337,69 @@
         obj->fRef.fGen = gen;
     }
 
-
-    static void makeString(const unsigned char* start, SkPdfNativeObject* obj) {
-        makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType);
-    }
-
-    static void makeString(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
-        makeStringCore(start, end - start, obj, kString_PdfObjectType);
-    }
-
-    static void makeString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
-        makeStringCore(start, bytes, obj, kString_PdfObjectType);
+    static void resetAndMakeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        obj->reset();
+        makeReference(id, gen, obj PUT_TRACK_PARAMETERS);
     }
 
 
-    static void makeHexString(const unsigned char* start, SkPdfNativeObject* obj) {
-        makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType);
+    static void makeString(const unsigned char* start, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType PUT_TRACK_PARAMETERS);
     }
 
-    static void makeHexString(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
-        makeStringCore(start, end - start, obj, kHexString_PdfObjectType);
+    static void makeString(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        makeStringCore(start, end - start, obj, kString_PdfObjectType PUT_TRACK_PARAMETERS);
     }
 
-    static void makeHexString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
-        makeStringCore(start, bytes, obj, kHexString_PdfObjectType);
+    static void makeString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        makeStringCore(start, bytes, obj, kString_PdfObjectType PUT_TRACK_PARAMETERS);
     }
 
 
-    static void makeName(const unsigned char* start, SkPdfNativeObject* obj) {
-        makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType);
+    static void makeHexString(const unsigned char* start, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType PUT_TRACK_PARAMETERS);
     }
 
-    static void makeName(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
-        makeStringCore(start, end - start, obj, kName_PdfObjectType);
+    static void makeHexString(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        makeStringCore(start, end - start, obj, kHexString_PdfObjectType PUT_TRACK_PARAMETERS);
     }
 
-    static void makeName(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
-        makeStringCore(start, bytes, obj, kName_PdfObjectType);
+    static void makeHexString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        makeStringCore(start, bytes, obj, kHexString_PdfObjectType PUT_TRACK_PARAMETERS);
     }
 
 
-    static void makeKeyword(const unsigned char* start, SkPdfNativeObject* obj) {
-        makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType);
+    static void makeName(const unsigned char* start, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType PUT_TRACK_PARAMETERS);
     }
 
-    static void makeKeyword(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
-        makeStringCore(start, end - start, obj, kKeyword_PdfObjectType);
+    static void makeName(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        makeStringCore(start, end - start, obj, kName_PdfObjectType PUT_TRACK_PARAMETERS);
     }
 
-    static void makeKeyword(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
-        makeStringCore(start, bytes, obj, kKeyword_PdfObjectType);
+    static void makeName(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        makeStringCore(start, bytes, obj, kName_PdfObjectType PUT_TRACK_PARAMETERS);
+    }
+
+
+    static void makeKeyword(const unsigned char* start, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType PUT_TRACK_PARAMETERS);
+    }
+
+    static void makeKeyword(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        makeStringCore(start, end - start, obj, kKeyword_PdfObjectType PUT_TRACK_PARAMETERS);
+    }
+
+    static void makeKeyword(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        makeStringCore(start, bytes, obj, kKeyword_PdfObjectType PUT_TRACK_PARAMETERS);
     }
 
 
 
     // TODO(edisonn): make the functions to return SkPdfArray, move these functions in SkPdfArray
-    static void makeEmptyArray(SkPdfNativeObject* obj) {
+    static void makeEmptyArray(SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        STORE_TRACK_PARAMETERS(obj);
+
         SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
 
         obj->fObjectType = kArray_PdfObjectType;
@@ -427,7 +470,9 @@
 
 
     // TODO(edisonn): make the functions to return SkPdfDictionary, move these functions in SkPdfDictionary
-    static void makeEmptyDictionary(SkPdfNativeObject* obj) {
+    static void makeEmptyDictionary(SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
+        STORE_TRACK_PARAMETERS(obj);
+
         SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
 
         obj->fObjectType = kDictionary_PdfObjectType;
@@ -1144,15 +1189,17 @@
     }
 
 private:
-    static void makeStringCore(const unsigned char* start, SkPdfNativeObject* obj, ObjectType type) {
-        makeStringCore(start, strlen((const char*)start), obj, type);
+    static void makeStringCore(const unsigned char* start, SkPdfNativeObject* obj, ObjectType type GET_TRACK_PARAMETERS) {
+        makeStringCore(start, strlen((const char*)start), obj, type PUT_TRACK_PARAMETERS);
     }
 
-    static void makeStringCore(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj, ObjectType type) {
-        makeStringCore(start, end - start, obj, type);
+    static void makeStringCore(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj, ObjectType type GET_TRACK_PARAMETERS) {
+        makeStringCore(start, end - start, obj, type PUT_TRACK_PARAMETERS);
     }
 
-    static void makeStringCore(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj, ObjectType type) {
+    static void makeStringCore(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj, ObjectType type GET_TRACK_PARAMETERS) {
+        STORE_TRACK_PARAMETERS(obj);
+
         SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
 
         obj->fObjectType = type;
@@ -1175,11 +1222,11 @@
 
 class SkPdfName : public SkPdfNativeObject {
     SkPdfName() : SkPdfNativeObject() {
-        SkPdfNativeObject::makeName((const unsigned char*)"", this);
+        SkPdfNativeObject::makeName((const unsigned char*)"", this PUT_TRACK_PARAMETERS_SRC);
     }
 public:
     SkPdfName(char* name) : SkPdfNativeObject() {
-        this->makeName((const unsigned char*)name, this);
+        this->makeName((const unsigned char*)name, this PUT_TRACK_PARAMETERS_SRC);
     }
 };
 
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
index 73f42fa..4e0e4c4 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
@@ -135,7 +135,9 @@
 }
 
 // last elem has to be ]
-static const unsigned char* readArray(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* array, SkPdfAllocator* allocator, SkPdfNativeDoc* doc) {
+static const unsigned char* readArray(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* array, SkPdfAllocator* allocator, SkPdfNativeDoc* doc GET_TRACK_STREAM) {
+    SkPdfNativeObject::makeEmptyArray(array PUT_TRACK_STREAM(start, start));
+
     if (allocator == NULL) {
         // TODO(edisonn): report/warning error
         return end;
@@ -158,14 +160,15 @@
         }
 
         SkPdfNativeObject* newObj = allocator->allocObject();
-        start = nextObject(level + 1, start, end, newObj, allocator, doc);
+        start = nextObject(level + 1, start, end, newObj, allocator, doc PUT_TRACK_STREAM_ARGS);
         // 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()) {
             SkPdfNativeObject* gen = array->removeLastInArray();
             SkPdfNativeObject* id = array->removeLastInArray();
-            newObj->reset();
-            SkPdfNativeObject::makeReference((unsigned int)id->intValue(), (unsigned int)gen->intValue(), newObj);
+
+            SkPdfNativeObject::resetAndMakeReference((unsigned int)id->intValue(), (unsigned int)gen->intValue(), newObj PUT_TRACK_PARAMETERS_OBJ2(id, newObj));
+
         }
         array->appendInArray(newObj);
     }
@@ -305,17 +308,17 @@
     return readString(level, start, end, NULL) - start;
 }
 
-static const unsigned char* readString(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* str, SkPdfAllocator* allocator) {
+static const unsigned char* readString(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* str, SkPdfAllocator* allocator GET_TRACK_STREAM) {
     if (!allocator) {
         return end;
     }
     int outLength = readStringLength(level, start, end);
     // TODO(edisonn): optimize the allocation, don't allocate new string, but put it in a preallocated buffer
     unsigned char* out = (unsigned char*)allocator->alloc(outLength);
-    start = readString(level, start, end, out);
-    SkPdfNativeObject::makeString(out, out + outLength, str);
+    const unsigned char* now = readString(level, start, end, out);
+    SkPdfNativeObject::makeString(out, out + outLength, str PUT_TRACK_STREAM(start, now));
     TRACE_STRING(out, out + outLength);
-    return start;  // consumed already ) at the end of the string
+    return now;  // consumed already ) at the end of the string
 }
 
 static const unsigned char* readHexString(int level, const unsigned char* start, const unsigned char* end, unsigned char* out) {
@@ -452,17 +455,17 @@
     return readHexString(level, start, end, NULL) - start;
 }
 
-static const unsigned char* readHexString(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* str, SkPdfAllocator* allocator) {
+static const unsigned char* readHexString(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* str, SkPdfAllocator* allocator GET_TRACK_STREAM) {
     if (!allocator) {
         return end;
     }
     int outLength = readHexStringLength(level, start, end);
     // TODO(edisonn): optimize the allocation, don't allocate new string, but put it in a preallocated buffer
     unsigned char* out = (unsigned char*)allocator->alloc(outLength);
-    start = readHexString(level, start, end, out);
-    SkPdfNativeObject::makeHexString(out, out + outLength, str);
+    const unsigned char* now = readHexString(level, start, end, out);
+    SkPdfNativeObject::makeHexString(out, out + outLength, str PUT_TRACK_STREAM(start, now));
     TRACE_HEXSTRING(out, out + outLength);
-    return start;  // consumed already > at the end of the string
+    return now;  // consumed already > at the end of the string
 }
 
 // TODO(edisonn): before PDF 1.2 name could not have special characters, add version parameter
@@ -577,17 +580,17 @@
     return readName(level, start, end, NULL) - start;
 }
 
-static const unsigned char* readName(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* name, SkPdfAllocator* allocator) {
+static const unsigned char* readName(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* name, SkPdfAllocator* allocator GET_TRACK_STREAM) {
     if (!allocator) {
         return end;
     }
     int outLength = readNameLength(level, start, end);
     // TODO(edisonn): optimize the allocation, don't allocate new string, but put it in a preallocated buffer
     unsigned char* out = (unsigned char*)allocator->alloc(outLength);
-    start = readName(level, start, end, out);
-    SkPdfNativeObject::makeName(out, out + outLength, name);
+    const unsigned char* now = readName(level, start, end, out);
+    SkPdfNativeObject::makeName(out, out + outLength, name PUT_TRACK_STREAM(start, now));
     TRACE_NAME(out, out + outLength);
-    return start;
+    return now;
 }
 
 // TODO(edisonn): pdf spec let Length to be an indirect object define after the stream
@@ -723,13 +726,13 @@
     return endEI;
 }
 
-static const unsigned char* readDictionary(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* dict, SkPdfAllocator* allocator, SkPdfNativeDoc* doc) {
+static const unsigned char* readDictionary(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* dict, SkPdfAllocator* allocator, SkPdfNativeDoc* doc GET_TRACK_STREAM) {
     if (allocator == NULL) {
         // TODO(edisonn): report/warning error
         return end;
     }
     TRACE_INDENT(level, "Dictionary");
-    SkPdfNativeObject::makeEmptyDictionary(dict);
+    SkPdfNativeObject::makeEmptyDictionary(dict PUT_TRACK_STREAM(start, start));
 
     start = skipPdfWhiteSpaces(level, start, end);
     SkPdfAllocator tmpStorage;  // keys will be stored in dict, we can free them immediately after set.
@@ -738,12 +741,12 @@
         SkPdfNativeObject key;
         //*start = '\0';
         start++;
-        start = readName(level + 1, start, end, &key, &tmpStorage);
+        start = readName(level + 1, start, end, &key, &tmpStorage PUT_TRACK_STREAM_ARGS);
         start = skipPdfWhiteSpaces(level + 1, start, end);
 
         if (start < end) {
             SkPdfNativeObject* value = allocator->allocObject();
-            start = nextObject(level + 1, start, end, value, allocator, doc);
+            start = nextObject(level + 1, start, end, value, allocator, doc PUT_TRACK_STREAM_ARGS);
 
             start = skipPdfWhiteSpaces(level + 1, start, end);
 
@@ -751,15 +754,14 @@
                 // seems we have an indirect reference
                 if (isPdfDigit(*start)) {
                     SkPdfNativeObject generation;
-                    start = nextObject(level + 1, start, end, &generation, allocator, doc);
+                    start = nextObject(level + 1, start, end, &generation, allocator, doc PUT_TRACK_STREAM_ARGS);
 
                     SkPdfNativeObject keywordR;
-                    start = nextObject(level + 1, start, end, &keywordR, allocator, doc);
+                    start = nextObject(level + 1, start, end, &keywordR, allocator, doc PUT_TRACK_STREAM_ARGS);
 
                     if (value->isInteger() && generation.isInteger() && keywordR.isKeywordReference()) {
                         int64_t id = value->intValue();
-                        value->reset();
-                        SkPdfNativeObject::makeReference((unsigned int)id, (unsigned int)generation.intValue(), value);
+                        SkPdfNativeObject::resetAndMakeReference((unsigned int)id, (unsigned int)generation.intValue(), value PUT_TRACK_PARAMETERS_OBJ2(value, &generation));
                         dict->set(&key, value);
                     } else {
                         // error, ignore
@@ -796,12 +798,14 @@
     //*start = '\0';
     start++;  // skip >
 
+    STORE_TRACK_PARAMETER_OFFSET_END(dict,start);
+
     start = readStream(level, start, end, dict, doc);
 
     return start;
 }
 
-const unsigned char* nextObject(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* token, SkPdfAllocator* allocator, SkPdfNativeDoc* doc) {
+const unsigned char* nextObject(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* token, SkPdfAllocator* allocator, SkPdfNativeDoc* doc GET_TRACK_STREAM) {
     const unsigned char* current;
 
     // skip white spaces
@@ -821,26 +825,25 @@
         switch (*start) {
             case kOpenedSquareBracket_PdfDelimiter:
                 //*start = '\0';
-                SkPdfNativeObject::makeEmptyArray(token);
-                return readArray(level + 1, current, end, token, allocator, doc);
+                return readArray(level + 1, current, end, token, allocator, doc PUT_TRACK_STREAM_ARGS);
 
             case kOpenedRoundBracket_PdfDelimiter:
                 //*start = '\0';
-                return readString(level, start + 1, end, token, allocator);
+                return readString(level, start + 1, end, token, allocator PUT_TRACK_STREAM_ARGS);
 
             case kOpenedInequityBracket_PdfDelimiter:
                 //*start = '\0';
                 if (end > start + 1 && start[1] == kOpenedInequityBracket_PdfDelimiter) {
                     //start[1] = '\0';  // optional
                     // TODO(edisonn): pass here the length somehow?
-                    return readDictionary(level + 1, start + 2, end, token, allocator, doc);  // skip <<
+                    return readDictionary(level + 1, start + 2, end, token, allocator, doc PUT_TRACK_STREAM_ARGS);  // skip <<
                 } else {
-                    return readHexString(level, start + 1, end, token, allocator);  // skip <
+                    return readHexString(level, start + 1, end, token, allocator PUT_TRACK_STREAM_ARGS);  // skip <
                 }
 
             case kNamed_PdfDelimiter:
                 //*start = '\0';
-                return readName(level, start + 1, end, token, allocator);
+                return readName(level, start + 1, end, token, allocator PUT_TRACK_STREAM_ARGS);
 
             // TODO(edisonn): what to do curly brackets? read spec!
             case kOpenedCurlyBracket_PdfDelimiter:
@@ -856,24 +859,24 @@
     }
 
     if (tokenLen == 4 && start[0] == 'n' && start[1] == 'u' && start[2] == 'l' && start[3] == 'l') {
-        SkPdfNativeObject::makeNull(token);
+        SkPdfNativeObject::makeNull(token PUT_TRACK_STREAM(start, start + 4));
         return current;
     }
 
     if (tokenLen == 4 && start[0] == 't' && start[1] == 'r' && start[2] == 'u' && start[3] == 'e') {
-        SkPdfNativeObject::makeBoolean(true, token);
+        SkPdfNativeObject::makeBoolean(true, token PUT_TRACK_STREAM(start, start + 4));
         return current;
     }
 
     if (tokenLen == 5 && start[0] == 'f' && start[1] == 'a' && start[2] == 'l' && start[3] == 's' && start[4] == 'e') {
-        SkPdfNativeObject::makeBoolean(false, token);
+        SkPdfNativeObject::makeBoolean(false, token PUT_TRACK_STREAM(start, start + 5));
         return current;
     }
 
     if (isPdfNumeric(*start)) {
-        SkPdfNativeObject::makeNumeric(start, current, token);
+        SkPdfNativeObject::makeNumeric(start, current, token PUT_TRACK_STREAM(start, current));
     } else {
-        SkPdfNativeObject::makeKeyword(start, current, token);
+        SkPdfNativeObject::makeKeyword(start, current, token PUT_TRACK_STREAM(start, current));
     }
     return current;
 }
@@ -950,7 +953,7 @@
         return false;
     }
 
-    fUncompressedStream = nextObject(0, fUncompressedStream, fUncompressedStreamEnd, &obj, fAllocator, fDoc);
+    fUncompressedStream = nextObject(0, fUncompressedStream, fUncompressedStreamEnd, &obj, fAllocator, fDoc PUT_TRACK_STREAM_ARGS_EXPL2(fStreamId, fUncompressedStreamStart));
 
     // If it is a keyword, we will only get the pointer of the string
     if (obj.type() == SkPdfNativeObject::kKeyword_PdfObjectType) {
@@ -1085,18 +1088,18 @@
     }
 
     SkPdfImageDictionary* inlineImage = (SkPdfImageDictionary*)fAllocator->allocObject();
-    SkPdfNativeObject::makeEmptyDictionary(inlineImage);
+    SkPdfNativeObject::makeEmptyDictionary(inlineImage PUT_TRACK_STREAM_ARGS_EXPL(fStreamId, fUncompressedStream - fUncompressedStreamStart, fUncompressedStream - fUncompressedStreamStart));
 
     while (fUncompressedStream < fUncompressedStreamEnd) {
         SkPdfNativeObject* key = fAllocator->allocObject();
-        fUncompressedStream = nextObject(0, fUncompressedStream, fUncompressedStreamEnd, key, fAllocator, fDoc);
+        fUncompressedStream = nextObject(0, fUncompressedStream, fUncompressedStreamEnd, key, fAllocator, fDoc PUT_TRACK_STREAM_ARGS_EXPL2(fStreamId, fUncompressedStreamStart));
 
         if (key->isKeyword() && key->lenstr() == 2 && key->c_str()[0] == 'I' && key->c_str()[1] == 'D') { // ID
             fUncompressedStream = readInlineImageStream(0, fUncompressedStream, fUncompressedStreamEnd, inlineImage, fDoc);
             return inlineImage;
         } else {
             SkPdfNativeObject* obj = fAllocator->allocObject();
-            fUncompressedStream = nextObject(0, fUncompressedStream, fUncompressedStreamEnd, obj, fAllocator, fDoc);
+            fUncompressedStream = nextObject(0, fUncompressedStream, fUncompressedStreamEnd, obj, fAllocator, fDoc PUT_TRACK_STREAM_ARGS_EXPL2(fStreamId, fUncompressedStreamStart));
             // TODO(edisonn): perf maybe we should not expand abreviation like this
             inlineImage->set(inlineImageKeyAbbreviationExpand(key),
                              inlineImageValueAbbreviationExpand(obj));
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h
index 56bf263..53169ca 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h
@@ -8,6 +8,8 @@
 #ifndef SkPdfNativeTokenizer_DEFINED
 #define SkPdfNativeTokenizer_DEFINED
 
+#include "SkPdfConfig.h"
+
 #include "SkTDArray.h"
 #include "SkTDict.h"
 #include <math.h>
@@ -116,7 +118,7 @@
 };
 
 class SkPdfNativeDoc;
-const unsigned char* nextObject(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* token, SkPdfAllocator* allocator, SkPdfNativeDoc* doc);
+const unsigned char* nextObject(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* token, SkPdfAllocator* allocator, SkPdfNativeDoc* doc GET_TRACK_STREAM);
 
 enum SkPdfTokenType {
     kKeyword_TokenType,
@@ -155,6 +157,10 @@
     bool fEmpty;
     bool fHasPutBack;
     PdfToken fPutBack;
+
+#ifdef PDF_TRACK_STREAM_OFFSETS
+    int fStreamId;
+#endif  // PDF_TRACK_STREAM_OFFSETS
 };
 
 #endif  // SkPdfNativeTokenizer_DEFINED