isolate podofo to prepare for native parser, autogenerate PDF API during build

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

git-svn-id: http://skia.googlecode.com/svn/trunk@9879 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/PdfViewer/SkPdfBasics.h b/experimental/PdfViewer/SkPdfBasics.h
index 894db10..d20f34b 100644
--- a/experimental/PdfViewer/SkPdfBasics.h
+++ b/experimental/PdfViewer/SkPdfBasics.h
@@ -3,24 +3,22 @@
 
 #include "SkCanvas.h"
 #include "SkPaint.h"
+#include "SkPdfConfig.h"
 
 #include <iostream>
 #include <cstdio>
+#include <map>
 #include <stack>
 
-#define PDF_TRACE
-//#define PDF_TRACE_DIFF_IN_PNG
-//#define PDF_DEBUG_NO_CLIPING
-//#define PDF_DEBUG_NO_PAGE_CLIPING
-//#define PDF_DEBUG_3X
-
 class SkPdfFont;
 class SkPdfDoc;
 class SkPdfObject;
 class SkPdfResourceDictionary;
 
+class SkPodofoParsedPDF;
+
 // TODO(edisonn): better class design.
-struct PdfColorOperator {
+struct SkPdfColorOperator {
     std::string fColorSpace;  // TODO(edisonn): use SkString
     SkColor fColor;
     double fOpacity;  // ca or CA
@@ -31,7 +29,7 @@
         fColor = color;
     }
     // TODO(edisonn): double check the default values for all fields.
-    PdfColorOperator() : fColor(SK_ColorBLACK), fOpacity(1) {}
+    SkPdfColorOperator() : fColor(SK_ColorBLACK), fOpacity(1) {}
 
     void applyGraphicsState(SkPaint* paint) {
         paint->setColor(SkColorSetA(fColor, fOpacity * 255));
@@ -39,7 +37,7 @@
 };
 
 // TODO(edisonn): better class design.
-struct PdfGraphicsState {
+struct SkPdfGraphicsState {
     SkMatrix            fMatrix;
     SkMatrix            fMatrixTm;
     SkMatrix            fMatrixTlm;
@@ -57,19 +55,19 @@
     bool                fHasClipPathToApply;
     SkPath              fClipPath;
 
-    PdfColorOperator    fStroking;
-    PdfColorOperator    fNonStroking;
+    SkPdfColorOperator  fStroking;
+    SkPdfColorOperator  fNonStroking;
 
     double              fLineWidth;
     double              fTextLeading;
     double              fWordSpace;
     double              fCharSpace;
 
-    SkPdfResourceDictionary* fResources;
+    const SkPdfResourceDictionary* fResources;
 
     SkBitmap            fSMask;
 
-    PdfGraphicsState() {
+    SkPdfGraphicsState() {
         fCurPosX      = 0.0;
         fCurPosY      = 0.0;
         fCurFontSize  = 0.0;
@@ -104,26 +102,30 @@
 };
 
 // TODO(edisonn): better class design.
-struct PdfInlineImage {
+// TODO(edisonn): could we remove it?
+// TODO(edisonn): rename to SkPdfInlineImage
+struct SkPdfInlineImage {
     std::map<std::string, std::string> fKeyValuePairs;
     std::string fImageData;
 };
 
 // TODO(edisonn): better class design.
+// TODO(edisonn): rename to SkPdfContext
 struct PdfContext {
     std::stack<SkPdfObject*>        fObjectStack;
-    std::stack<PdfGraphicsState>    fStateStack;
-    PdfGraphicsState                fGraphicsState;
-    SkPdfDoc*                       fPdfDoc;
+    std::stack<SkPdfGraphicsState>  fStateStack;
+    SkPdfGraphicsState              fGraphicsState;
+    const SkPodofoParsedPDF*        fPdfDoc;
     SkMatrix                        fOriginalMatrix;
 
-    PdfInlineImage                  fInlineImage;
+    SkPdfInlineImage                fInlineImage;
 
-    PdfContext(SkPdfDoc* doc) :  fPdfDoc(doc) {}
+    PdfContext(const SkPodofoParsedPDF* doc) :  fPdfDoc(doc) {}
 
 };
 
-//  TODO(edisonn): temporary code, to report how much of the PDF we actually think we rendered.
+// TODO(edisonn): temporary code, to report how much of the PDF we actually think we rendered.
+// TODO(edisonn): rename to SkPdfResult
 enum PdfResult {
     kOK_PdfResult,
     kPartial_PdfResult,
diff --git a/experimental/PdfViewer/SkPdfConfig.h b/experimental/PdfViewer/SkPdfConfig.h
new file mode 100644
index 0000000..1092de1
--- /dev/null
+++ b/experimental/PdfViewer/SkPdfConfig.h
@@ -0,0 +1,19 @@
+#ifndef __DEFINED__SkPdfConfig
+#define __DEFINED__SkPdfConfig
+
+//#define PDF_TRACE
+//#define PDF_TRACE_DIFF_IN_PNG
+//#define PDF_DEBUG_NO_CLIPING
+//#define PDF_DEBUG_NO_PAGE_CLIPING
+//#define PDF_DEBUG_3X
+
+// TODO(edisonn): move in trace util.
+#ifdef PDF_TRACE
+void SkTraceMatrix(const SkMatrix& matrix, const char* sz);
+void SkTraceRect(const SkRect& rect, const char* sz);
+#else
+#define SkTraceMatrix(a,b)
+#define SkTraceRect(a,b)
+#endif
+
+#endif  // __DEFINED__SkPdfConfig
diff --git a/experimental/PdfViewer/SkPdfFont.cpp b/experimental/PdfViewer/SkPdfFont.cpp
index e0cbd2c..733ae87 100644
--- a/experimental/PdfViewer/SkPdfFont.cpp
+++ b/experimental/PdfViewer/SkPdfFont.cpp
@@ -3,6 +3,7 @@
 
 #include "SkStream.h"
 #include "SkTypeface.h"
+#include "SkPdfPodofoTokenizer.h"
 
 std::map<std::string, SkPdfStandardFontEntry>& getStandardFonts() {
     static std::map<std::string, SkPdfStandardFontEntry> gPdfStandardFonts;
@@ -164,21 +165,17 @@
         }
     }
 
-    if (!pdfStream || !pdfStream->podofo()->GetStream()) {
-        // TODO(edisonn): report warning to be used in testing.
-        return NULL;
-    }
-
     char* uncompressedStream = NULL;
-    pdf_long uncompressedStreamLength = 0;
+    long uncompressedStreamLength = 0;
 
-    // TODO(edisonn): get rid of try/catch exceptions! We should not throw on user data!
-    try {
-        pdfStream->podofo()->GetStream()->GetFilteredCopy(&uncompressedStream, &uncompressedStreamLength);
-    } catch (PdfError& e) {
-        // TODO(edisonn): report warning to be used in testing.
+    // TODO(edisonn): report warning to be used in testing.
+    if (!pdfStream ||
+            !pdfStream->GetFilteredCopy(&uncompressedStream, &uncompressedStreamLength) ||
+            !uncompressedStream ||
+            !uncompressedStreamLength) {
         return NULL;
     }
+
     SkMemoryStream* skStream = new SkMemoryStream(uncompressedStream, uncompressedStreamLength);
     SkTypeface* face = SkTypeface::CreateFromStream(skStream);
 
@@ -199,12 +196,11 @@
     }
 
     // TODO(edisonn): perf - make a map
-    for (int i = 0 ; i < obj->doc()->GetObjects().GetSize(); i++) {
-        PdfVecObjects& objects = (PdfVecObjects&)obj->doc()->GetObjects();
-        const PdfObject* podofoFont = objects[i];
+    for (int i = 0 ; i < obj->doc()->objects(); i++) {
+        const SkPdfObject* podofoFont = obj->doc()->object(i);
         SkPdfFontDescriptorDictionary* fd = NULL;
 
-        if (mapFontDescriptorDictionary(*obj->doc(), *podofoFont, &fd)) {
+        if (obj->doc()->mapper()->mapFontDescriptorDictionary(podofoFont, &fd)) {
             if (fd->has_FontName() && fd->FontName() == fontName) {
                 SkPdfFont* font = SkPdfFont::fontFromFontDescriptor(fd, false);
                 if (font) {
@@ -289,8 +285,8 @@
 
 static int skstoi(const SkPdfString* str) {
     int ret = 0;
-    for (int i = 0 ; i < str->podofo()->GetString().GetLength(); i++) {
-        ret = (ret << 8) + ((unsigned char*)str->podofo()->GetString().GetString())[i];
+    for (int i = 0 ; i < str->len(); i++) {
+        ret = (ret << 8) + ((unsigned char*)str->c_str())[i];
     }
     return ret;
 }
@@ -300,7 +296,7 @@
     fCMapEncodingFlag = NULL;
 
     if (stream) {
-        SkPdfTokenizer tokenizer(stream);
+        SkPdfPodofoTokenizer* tokenizer = stream->doc()->tokenizerOfStream(stream);
         PdfToken token;
 
         fCMapEncoding = new unsigned short[256 * 256];
@@ -316,15 +312,15 @@
         //<0000> <005E> <0020>
         //<005F> <0061> [<00660066> <00660069> <00660066006C>]
 
-        while (tokenizer.readToken(&token)) {
+        while (tokenizer->readToken(&token)) {
 
             if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "begincodespacerange") == 0) {
-                while (tokenizer.readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endcodespacerange") == 0)) {
-//                    tokenizer.PutBack(token);
-//                    tokenizer.readToken(&token);
+                while (tokenizer->readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endcodespacerange") == 0)) {
+//                    tokenizer->PutBack(token);
+//                    tokenizer->readToken(&token);
                     // TODO(edisonn): check token type! ignore/report errors.
                     int start = skstoi(token.fObject->asString());
-                    tokenizer.readToken(&token);
+                    tokenizer->readToken(&token);
                     int end = skstoi(token.fObject->asString());
                     for (int i = start; i <= end; i++) {
                         fCMapEncodingFlag[i] |= 1;
@@ -333,11 +329,11 @@
             }
 
             if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "beginbfchar") == 0) {
-                while (tokenizer.readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfchar") == 0)) {
-//                    tokenizer.PutBack(token);
-//                    tokenizer.readToken(&token);
+                while (tokenizer->readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfchar") == 0)) {
+//                    tokenizer->PutBack(token);
+//                    tokenizer->readToken(&token);
                     int from = skstoi(token.fObject->asString());
-                    tokenizer.readToken(&token);
+                    tokenizer->readToken(&token);
                     int to = skstoi(token.fObject->asString());
 
                     fCMapEncodingFlag[from] |= 2;
@@ -346,19 +342,19 @@
             }
 
             if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "beginbfrange") == 0) {
-                while (tokenizer.readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfrange") == 0)) {
-//                    tokenizer.PutBack(token);
-//                    tokenizer.readToken(&token);
+                while (tokenizer->readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfrange") == 0)) {
+//                    tokenizer->PutBack(token);
+//                    tokenizer->readToken(&token);
                     int start = skstoi(token.fObject->asString());
-                    tokenizer.readToken(&token);
+                    tokenizer->readToken(&token);
                     int end = skstoi(token.fObject->asString());
 
 
-                    tokenizer.readToken(&token); // [ or just an array directly?
-//                    tokenizer.PutBack(token);
+                    tokenizer->readToken(&token); // [ or just an array directly?
+//                    tokenizer->PutBack(token);
 
                     if (token.fType == kObject_TokenType && token.fObject->asString()) {
-//                        tokenizer.readToken(&token);
+//                        tokenizer->readToken(&token);
                         int value = skstoi(token.fObject->asString());
 
                         for (int i = start; i <= end; i++) {
@@ -370,7 +366,7 @@
 
                         // read one string
                     } else if (token.fType == kObject_TokenType && token.fObject->asArray()) {
-//                        tokenizer.readToken(&token);
+//                        tokenizer->readToken(&token);
                         for (int i = 0; i < token.fObject->asArray()->size(); i++) {
                             fCMapEncodingFlag[start + i] |= 2;
                             fCMapEncoding[start + i] = skstoi((*token.fObject->asArray())[i]->asString());
diff --git a/experimental/PdfViewer/SkPdfFont.h b/experimental/PdfViewer/SkPdfFont.h
index 90fe3b0..1e9d9ee 100644
--- a/experimental/PdfViewer/SkPdfFont.h
+++ b/experimental/PdfViewer/SkPdfFont.h
@@ -2,7 +2,7 @@
 #define __DEFINED__SkPdfFont
 
 #include "SkPdfHeaders_autogen.h"
-#include "SkPdfPodofoMapper_autogen.h"
+#include "SkPdfMapper_autogen.h"
 
 #include <map>
 #include <string>
@@ -36,9 +36,9 @@
     int len;
 
 public:
-    SkUnencodedText(const SkPdfObject* obj) {
-        text = (void*)obj->podofo()->GetString().GetString();
-        len = obj->podofo()->GetString().GetLength();
+    SkUnencodedText(const SkPdfString* obj) {
+        text = (void*)obj->c_str();
+        len = obj->len();
     }
 };
 
diff --git a/experimental/PdfViewer/SkPdfParser.cpp b/experimental/PdfViewer/SkPdfParser.cpp
index e4c545f..0302512 100644
--- a/experimental/PdfViewer/SkPdfParser.cpp
+++ b/experimental/PdfViewer/SkPdfParser.cpp
@@ -37,8 +37,17 @@
 // TODO(edisonn): put drawtext in #ifdefs, so comparations will ignore minor changes in text positioning and font
 // this way, we look more at other features and layout in diffs
 
+// TODO(edisonn): move trace dump in the get functions, and mapper ones too so it ghappens automatically
+/*
+#ifdef PDF_TRACE
+    std::string str;
+    pdfContext->fGraphicsState.fResources->podofo()->ToString(str);
+    printf("Print Tf Resources: %s\n", str.c_str());
+#endif
+ */
+
 #include "SkPdfHeaders_autogen.h"
-#include "SkPdfPodofoMapper_autogen.h"
+#include "SkPdfMapper_autogen.h"
 #include "SkPdfParser.h"
 
 #include "SkPdfBasics.h"
@@ -46,11 +55,6 @@
 
 #include "SkPdfFont.h"
 
-bool skpdfmap(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj, SkPdfObject** out) {
-    return mapObject(podofoDoc, podofoObj, out);
-}
-
-
 /*
  * TODO(edisonn):
  * - all font types and all ppdf font features
@@ -97,25 +101,7 @@
     }
 }
 
-const PdfObject* resolveReferenceObject(const PdfMemDocument* pdfDoc,
-                                  const PdfObject* obj,
-                                  bool resolveOneElementArrays) {
-    while (obj && (obj->IsReference() || (resolveOneElementArrays &&
-                                          obj->IsArray() &&
-                                          obj->GetArray().GetSize() == 1))) {
-        if (obj->IsReference()) {
-            // We need to force the non const, the only update we will do is for recurssion checks.
-            PdfReference& ref = (PdfReference&)obj->GetReference();
-            obj = pdfDoc->GetObjects().GetObject(ref);
-        } else {
-            obj = &obj->GetArray()[0];
-        }
-    }
-
-    return obj;
-}
-
-static SkMatrix SkMatrixFromPdfMatrix(double array[6]) {
+SkMatrix SkMatrixFromPdfMatrix(double array[6]) {
     SkMatrix matrix;
     matrix.setAll(SkDoubleToScalar(array[0]),
                   SkDoubleToScalar(array[2]),
@@ -135,17 +121,16 @@
 
     // TODO(edisonn): security issue, ret if size() != 6
     for (int i = 0; i < 6; i++) {
-        const PdfObject* elem = resolveReferenceObject(pdfArray->doc(), (*pdfArray)[i]->podofo());
-        if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) {
+        const SkPdfObject* elem = pdfArray->operator [](i);
+        if (elem == NULL || (!elem->asNumber() && !elem->asInteger())) {
             return SkMatrix::I();  // TODO(edisonn): report issue
         }
-        array[i] = elem->GetReal();
+        array[i] = elem->asNumber() ? elem->asNumber()->value() : elem->asInteger()->value();
     }
 
     return SkMatrixFromPdfMatrix(array);
 }
 
-PdfContext* gPdfContext = NULL;
 SkBitmap* gDumpBitmap = NULL;
 SkCanvas* gDumpCanvas = NULL;
 char gLastKeyword[100] = "";
@@ -167,7 +152,7 @@
 }
 
 // TODO(edisonn): Pass PdfContext and SkCanvasd only with the define for instrumentation.
-static bool readToken(SkPdfTokenizer* fTokenizer, PdfToken* token) {
+static bool readToken(SkPdfPodofoTokenizer* fTokenizer, PdfToken* token) {
     bool ret = fTokenizer->readToken(token);
 
     gReadOp++;
@@ -333,7 +318,7 @@
 }
 
 PdfResult DrawText(PdfContext* pdfContext,
-                   const SkPdfObject* str,
+                   const SkPdfObject* _str,
                    SkCanvas* canvas)
 {
 
@@ -342,6 +327,13 @@
         skfont = SkPdfFont::Default();
     }
 
+    const SkPdfString* str = _str->asString();
+
+    if (str == NULL) {
+        // TODO(edisonn): report warning
+        return kIgnoreError_PdfResult;
+    }
+
     SkUnencodedText binary(str);
 
     SkDecodedText decoded;
@@ -400,260 +392,6 @@
 PdfResult PdfOp_Tw(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper);
 PdfResult PdfOp_Tc(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper);
 
-// TODO(edisonn): deal with synonyms (/BPC == /BitsPerComponent), here or in GetKey?
-// Always pass long form in key, and have a map of long -> short key
-bool LongFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        long* data) {
-    const PdfObject* value = resolveReferenceObject(pdfDoc,
-                                              dict.GetKey(PdfName(key)));
-
-    if (value == NULL || !value->IsNumber()) {
-        return false;
-    }
-    if (data == NULL) {
-        return true;
-    }
-
-    *data = value->GetNumber();
-    return true;
-}
-
-bool LongFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        long* data) {
-    if (LongFromDictionary(pdfDoc, dict, key, data)) return true;
-    if (abr == NULL || *abr == '\0') return false;
-    return LongFromDictionary(pdfDoc, dict, abr, data);
-}
-
-bool DoubleFromDictionary(const PdfMemDocument* pdfDoc,
-                          const PdfDictionary& dict,
-                          const char* key,
-                          double* data) {
-    const PdfObject* value = resolveReferenceObject(pdfDoc,
-                                              dict.GetKey(PdfName(key)));
-
-    if (value == NULL || (!value->IsReal() && !value->IsNumber())) {
-        return false;
-    }
-    if (data == NULL) {
-        return true;
-    }
-
-    *data = value->GetReal();
-    return true;
-}
-
-bool DoubleFromDictionary(const PdfMemDocument* pdfDoc,
-                          const PdfDictionary& dict,
-                          const char* key,
-                          const char* abr,
-                          double* data) {
-    if (DoubleFromDictionary(pdfDoc, dict, key, data)) return true;
-    if (abr == NULL || *abr == '\0') return false;
-    return DoubleFromDictionary(pdfDoc, dict, abr, data);
-}
-
-
-bool BoolFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        bool* data) {
-    const PdfObject* value = resolveReferenceObject(pdfDoc,
-                                              dict.GetKey(PdfName(key)));
-
-    if (value == NULL || !value->IsBool()) {
-        return false;
-    }
-    if (data == NULL) {
-        return true;
-    }
-
-    *data = value->GetBool();
-    return true;
-}
-
-bool BoolFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        bool* data) {
-    if (BoolFromDictionary(pdfDoc, dict, key, data)) return true;
-    if (abr == NULL || *abr == '\0') return false;
-    return BoolFromDictionary(pdfDoc, dict, abr, data);
-}
-
-bool NameFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        std::string* data) {
-    const PdfObject* value = resolveReferenceObject(pdfDoc,
-                                              dict.GetKey(PdfName(key)),
-                                              true);
-    if (value == NULL || !value->IsName()) {
-        return false;
-    }
-    if (data == NULL) {
-        return true;
-    }
-
-    *data = value->GetName().GetName();
-    return true;
-}
-
-bool NameFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        std::string* data) {
-    if (NameFromDictionary(pdfDoc, dict, key, data)) return true;
-    if (abr == NULL || *abr == '\0') return false;
-    return NameFromDictionary(pdfDoc, dict, abr, data);
-}
-
-bool StringFromDictionary(const PdfMemDocument* pdfDoc,
-                          const PdfDictionary& dict,
-                          const char* key,
-                          std::string* data) {
-    const PdfObject* value = resolveReferenceObject(pdfDoc,
-                                              dict.GetKey(PdfName(key)),
-                                              true);
-    if (value == NULL || (!value->IsString() && !value->IsHexString())) {
-        return false;
-    }
-    if (data == NULL) {
-        return true;
-    }
-
-    *data = value->GetString().GetString();
-    return true;
-}
-
-bool StringFromDictionary(const PdfMemDocument* pdfDoc,
-                          const PdfDictionary& dict,
-                          const char* key,
-                          const char* abr,
-                          std::string* data) {
-    if (StringFromDictionary(pdfDoc, dict, key, data)) return true;
-    if (abr == NULL || *abr == '\0') return false;
-    return StringFromDictionary(pdfDoc, dict, abr, data);
-}
-
-/*
-bool ArrayFromDictionary(const PdfMemDocument* pdfDoc,
-                              const PdfDictionary& dict,
-                              const char* key,
-                              SkPdfArray** data) {
-    const PdfObject* value = resolveReferenceObject(pdfDoc,
-                                              dict.GetKey(PdfName(key)),
-                                              true);
-    if (value == NULL || !value->IsArray()) {
-        return false;
-    }
-    if (data == NULL) {
-        return true;
-    }
-
-    return mapArray(*pdfDoc, *value, data);
-}
-
-
-bool ArrayFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkPdfArray** data) {
-    if (ArrayFromDictionary(pdfDoc, dict, key, data)) return true;
-    if (abr == NULL || *abr == '\0') return false;
-    return ArrayFromDictionary(pdfDoc, dict, abr, data);
-}
-
-
-bool DictionaryFromDictionary(const PdfMemDocument* pdfDoc,
-                              const PdfDictionary& dict,
-                              const char* key,
-                              SkPdfDictionary** data) {
-    const PdfObject* value = resolveReferenceObject(pdfDoc,
-                                              dict.GetKey(PdfName(key)),
-                                              true);
-    if (value == NULL || !value->IsDictionary()) {
-        return false;
-    }
-    if (data == NULL) {
-        return true;
-    }
-
-    return mapDictionary(*pdfDoc, *value, data);
-}
-
-bool DictionaryFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkPdfDictionary** data) {
-    if (DictionaryFromDictionary(pdfDoc, dict, key, data)) return true;
-    if (abr == NULL || *abr == '\0') return false;
-    return DictionaryFromDictionary(pdfDoc, dict, abr, data);
-}
-
-
-bool ObjectFromDictionary(const PdfMemDocument* pdfDoc,
-                          const PdfDictionary& dict,
-                          const char* key,
-                          SkPdfObject** data) {
-    const PdfObject* value = resolveReferenceObject(pdfDoc,
-                                              dict.GetKey(PdfName(key)),
-                                              true);
-    if (value == NULL) {
-        return false;
-    }
-    if (data == NULL) {
-        return true;
-    }
-    return mapObject(*pdfDoc, *value, data);
-}
-
-bool ObjectFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkPdfObject** data) {
-    if (ObjectFromDictionary(pdfDoc, dict, key, data)) return true;
-    if (abr == NULL || *abr == '\0') return false;
-    return ObjectFromDictionary(pdfDoc, dict, abr, data);
-}
-
-bool StreamFromDictionary(const PdfMemDocument* pdfDoc,
-                          const PdfDictionary& dict,
-                          const char* key,
-                          SkPdfStream** data) {
-    const PdfObject* value = resolveReferenceObject(pdfDoc,
-                                              dict.GetKey(PdfName(key)),
-                                              true);
-    if (value == NULL) {
-        return false;
-    }
-    if (data == NULL) {
-        return true;
-    }
-    return mapStream(*pdfDoc, *value, data);
-}
-
-bool StreamFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkPdfStream** data) {
-    if (StreamFromDictionary(pdfDoc, dict, key, data)) return true;
-    if (abr == NULL || *abr == '\0') return false;
-    return StreamFromDictionary(pdfDoc, dict, abr, data);
-}
-*/
-
 // TODO(edisonn): perf!!!
 
 static SkColorTable* getGrayColortable() {
@@ -781,7 +519,7 @@
 // this functions returns the image, it does not look at the smask.
 
 SkBitmap getImageFromObject(PdfContext* pdfContext, const SkPdfImageDictionary* image, bool transparencyMask) {
-    if (image == NULL || !image->valid()) {
+    if (image == NULL) {
         // TODO(edisonn): report warning to be used in testing.
         return SkBitmap();
     }
@@ -820,16 +558,15 @@
     }
 */
 
-    const PdfObject* obj = image->podofo();
-
     char* uncompressedStream = NULL;
     pdf_long uncompressedStreamLength = 0;
 
     PdfResult ret = kPartial_PdfResult;
-    // TODO(edisonn): get rid of try/catch exceptions! We should not throw on user data!
-    try {
-        obj->GetStream()->GetFilteredCopy(&uncompressedStream, &uncompressedStreamLength);
-    } catch (PdfError& e) {
+    SkPdfStream* stream = NULL;
+    image->doc()->mapper()->mapStream(image, &stream);
+
+    if (!stream || !stream->GetFilteredCopy(&uncompressedStream, &uncompressedStreamLength) ||
+            uncompressedStream == NULL || uncompressedStreamLength == 0) {
         // TODO(edisonn): report warning to be used in testing.
         return SkBitmap();
     }
@@ -853,20 +590,10 @@
 }
 
 SkBitmap getSmaskFromObject(PdfContext* pdfContext, const SkPdfImageDictionary* obj) {
-    const PdfObject* sMask = resolveReferenceObject(&pdfContext->fPdfDoc->podofo(),
-                                              obj->podofo()->GetDictionary().GetKey(PdfName("SMask")));
-
-#ifdef PDF_TRACE
-    std::string str;
-    if (sMask) {
-        sMask->ToString(str);
-        printf("/SMask of /Subtype /Image: %s\n", str.c_str());
-    }
-#endif
+    const SkPdfImageDictionary* sMask = obj->SMask();
 
     if (sMask) {
-        SkPdfImageDictionary skxobjmask(&pdfContext->fPdfDoc->podofo(), sMask);
-        return getImageFromObject(pdfContext, &skxobjmask, true);
+        return getImageFromObject(pdfContext, sMask, true);
     }
 
     // TODO(edisonn): implement GS SMask. Default to empty right now.
@@ -874,7 +601,7 @@
 }
 
 PdfResult doXObject_Image(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfImageDictionary* skpdfimage) {
-    if (skpdfimage == NULL || !skpdfimage->valid()) {
+    if (skpdfimage == NULL) {
         return kIgnoreError_PdfResult;
     }
 
@@ -902,103 +629,12 @@
     return kPartial_PdfResult;
 }
 
-bool SkMatrixFromDictionary(const PdfMemDocument* pdfDoc,
-                            const PdfDictionary& dict,
-                            const char* key,
-                            SkMatrix** matrix) {
-    const PdfObject* value = resolveReferenceObject(pdfDoc,
-                                                    dict.GetKey(PdfName(key)));
-
-    if (value == NULL || !value->IsArray()) {
-        return false;
-    }
-
-    if (value->GetArray().GetSize() != 6) {
-        return false;
-    }
-
-    double array[6];
-    for (int i = 0; i < 6; i++) {
-        const PdfObject* elem = resolveReferenceObject(pdfDoc, &value->GetArray()[i]);
-        if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) {
-            return false;
-        }
-        array[i] = elem->GetReal();
-    }
-
-    *matrix = new SkMatrix();
-    **matrix = SkMatrixFromPdfMatrix(array);
-    return true;
-}
-
-bool SkMatrixFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkMatrix** data) {
-    if (SkMatrixFromDictionary(pdfDoc, dict, key, data)) return true;
-    if (abr == NULL || *abr == '\0') return false;
-    return SkMatrixFromDictionary(pdfDoc, dict, abr, data);
-
-}
-
-bool SkRectFromDictionary(const PdfMemDocument* pdfDoc,
-                          const PdfDictionary& dict,
-                          const char* key,
-                          SkRect** rect) {
-    const PdfObject* value = resolveReferenceObject(pdfDoc,
-                                                    dict.GetKey(PdfName(key)));
-
-    if (value == NULL || !value->IsArray()) {
-        return false;
-    }
-
-    if (value->GetArray().GetSize() != 4) {
-        return false;
-    }
-
-    double array[4];
-    for (int i = 0; i < 4; i++) {
-        const PdfObject* elem = resolveReferenceObject(pdfDoc, &value->GetArray()[i]);
-        if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) {
-            return false;
-        }
-        array[i] = elem->GetReal();
-    }
-
-    *rect = new SkRect();
-    **rect = SkRect::MakeLTRB(SkDoubleToScalar(array[0]),
-                              SkDoubleToScalar(array[1]),
-                              SkDoubleToScalar(array[2]),
-                              SkDoubleToScalar(array[3]));
-    return true;
-}
-
-bool SkRectFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkRect** data) {
-    if (SkRectFromDictionary(pdfDoc, dict, key, data)) return true;
-    if (abr == NULL || *abr == '\0') return false;
-    return SkRectFromDictionary(pdfDoc, dict, abr, data);
-
-}
 
 
-SkPdfObject* get(const SkPdfObject* obj, const char* key, const char* abr = "") {
-    SkPdfObject* ret = NULL;
-    if (obj == NULL) return NULL;
-    const SkPdfDictionary* dict = obj->asDictionary();
-    if (dict == NULL) return NULL;
-    if (!dict->podofo()->IsDictionary()) return NULL;
-    ObjectFromDictionary(dict->doc(), dict->podofo()->GetDictionary(), key, abr, &ret);
-    return ret;
-}
 
 PdfResult doXObject_Form(PdfContext* pdfContext, SkCanvas* canvas, SkPdfType1FormDictionary* skobj) {
-    if (!skobj || !skobj->podofo() || !skobj->podofo()->HasStream() || skobj->podofo()->GetStream() == NULL || skobj->podofo()->GetStream()->GetLength() == 0) {
-        return kOK_PdfResult;
+    if (!skobj) {
+        return kIgnoreError_PdfResult;
     }
 
     PdfOp_q(pdfContext, canvas, NULL);
@@ -1029,16 +665,21 @@
     // TODO(edisonn): iterate smart on the stream even if it is compressed, tokenize it as we go.
     // For this PdfContentsTokenizer needs to be extended.
 
-    PdfResult ret = kPartial_PdfResult;
-    SkPdfTokenizer tokenizer(skobj);
-    PdfMainLooper looper(NULL, &tokenizer, pdfContext, canvas);
-    looper.loop();
+    SkPdfStream* stream = NULL;
+    skobj->doc()->mapper()->mapStream(skobj, &stream);
+
+    SkPdfPodofoTokenizer* tokenizer = skobj->doc()->tokenizerOfStream(stream);
+    if (tokenizer != NULL) {
+        PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas);
+        looper.loop();
+        delete tokenizer;
+    }
 
     // TODO(edisonn): should we restore the variable stack at the same state?
     // There could be operands left, that could be consumed by a parent tokenizer when we pop.
     canvas->restore();
     PdfOp_Q(pdfContext, canvas, NULL);
-    return ret;
+    return kPartial_PdfResult;
 }
 
 PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject& obj) {
@@ -1046,8 +687,8 @@
 }
 
 PdfResult doType3Char(PdfContext* pdfContext, SkCanvas* canvas, SkPdfObject* skobj, SkRect bBox, SkMatrix matrix, double textSize) {
-    if (!skobj || !skobj->podofo() || !skobj->podofo()->HasStream() || skobj->podofo()->GetStream() == NULL || skobj->podofo()->GetStream()->GetLength() == 0) {
-        return kOK_PdfResult;
+    if (!skobj) {
+        return kIgnoreError_PdfResult;
     }
 
     PdfOp_q(pdfContext, canvas, NULL);
@@ -1073,52 +714,58 @@
     // TODO(edisonn): iterate smart on the stream even if it is compressed, tokenize it as we go.
     // For this PdfContentsTokenizer needs to be extended.
 
-    PdfResult ret = kPartial_PdfResult;
-    SkPdfTokenizer tokenizer(skobj);
-    PdfMainLooper looper(NULL, &tokenizer, pdfContext, canvas);
-    looper.loop();
+    SkPdfStream* stream = NULL;
+    skobj->doc()->mapper()->mapStream(skobj, &stream);
+
+    SkPdfPodofoTokenizer* tokenizer = skobj->doc()->tokenizerOfStream(stream);
+    if (tokenizer != NULL) {
+        PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas);
+        looper.loop();
+        delete tokenizer;
+    }
 
     // TODO(edisonn): should we restore the variable stack at the same state?
     // There could be operands left, that could be consumed by a parent tokenizer when we pop.
     canvas->restore();
     PdfOp_Q(pdfContext, canvas, NULL);
-    return ret;
+
+    return kPartial_PdfResult;
 }
 
 
 // TODO(edisonn): faster, have the property on the SkPdfObject itself?
-std::set<const PdfObject*> gInRendering;
+std::set<const void*> gInRendering;
 
 class CheckRecursiveRendering {
-    const PdfObject& fObj;
+    const void* fUniqueData;
 public:
-    CheckRecursiveRendering(const PdfObject& obj) : fObj(obj) {
-        gInRendering.insert(&obj);
+    CheckRecursiveRendering(const SkPdfObject* obj) : fUniqueData(obj->data()) {
+        gInRendering.insert(obj);
     }
 
     ~CheckRecursiveRendering() {
         //SkASSERT(fObj.fInRendering);
-        gInRendering.erase(&fObj);
+        gInRendering.erase(fUniqueData);
     }
 
-    static bool IsInRendering(const PdfObject& obj) {
-        return gInRendering.find(&obj) != gInRendering.end();
+    static bool IsInRendering(const SkPdfObject* obj) {
+        return gInRendering.find(obj->data()) != gInRendering.end();
     }
 };
 
 PdfResult doXObject(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfObject& obj) {
-    if (CheckRecursiveRendering::IsInRendering(*obj.podofo())) {
+    if (CheckRecursiveRendering::IsInRendering(&obj)) {
         // Oops, corrupt PDF!
         return kIgnoreError_PdfResult;
     }
 
-    CheckRecursiveRendering checkRecursion(*obj.podofo());
+    CheckRecursiveRendering checkRecursion(&obj);
 
     // TODO(edisonn): check type
     SkPdfXObjectDictionary* skobj = NULL;
-    if (!mapXObjectDictionary(obj, &skobj)) return kIgnoreError_PdfResult;
+    if (!obj.doc()->mapper()->mapXObjectDictionary(&obj, &skobj)) return kIgnoreError_PdfResult;
 
-    if (!skobj || !skobj->valid()) return kIgnoreError_PdfResult;
+    if (!skobj) return kIgnoreError_PdfResult;
 
     PdfResult ret = kIgnoreError_PdfResult;
     switch (skobj->getType())
@@ -1178,7 +825,7 @@
         printf("%f ", array[i]);
     }
     printf("\n");
-    SkTraceMatrix(pdfContext->fGraphicsState.fMatrix);
+    SkTraceMatrix(pdfContext->fGraphicsState.fMatrix, "cm");
 #endif
 
     return kOK_PdfResult;
@@ -1213,18 +860,26 @@
     double tx = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->fObjectStack.pop();
 
     // TODO(edisonn): Create factory methods or constructors so podofo is hidden
-    PdfObject _ty(PdfVariant(-ty));
-    pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &_ty));
+    SkPdfNumber* _ty = pdfContext->fPdfDoc->createNumber(-ty);
+    pdfContext->fObjectStack.push(_ty);
 
     PdfOp_TL(pdfContext, canvas, looper);
 
-    PdfObject vtx(PdfVariant(-(-tx)));  // TODO(edisonn): Hmm, the compiler thinks I have here a function pointer if we use (tx), but not -(-tx)
-    pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &vtx));
+    SkPdfNumber* vtx = pdfContext->fPdfDoc->createNumber(tx);
+    pdfContext->fObjectStack.push(vtx);
 
-    PdfObject vty(PdfVariant(-(-ty)));
-    pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &vty));
+    SkPdfNumber* vty = pdfContext->fPdfDoc->createNumber(ty);
+    pdfContext->fObjectStack.push(vty);
 
-    return PdfOp_Td(pdfContext, canvas, looper);
+    PdfResult ret = PdfOp_Td(pdfContext, canvas, looper);
+
+    // TODO(edisonn): delete all the objects after rendering was complete, in this way pdf is rendered faster
+    // and the cleanup can happen while the user looks at the image
+    delete _ty;
+    delete vtx;
+    delete vty;
+
+    return ret;
 }
 
 PdfResult PdfOp_Tm(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
@@ -1257,12 +912,18 @@
 //0 Tl Td
 //where Tl is the current leading parameter in the text state
 PdfResult PdfOp_T_star(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
-    PdfObject zero(PdfVariant(0.0));
-    PdfObject tl(PdfVariant(-(-pdfContext->fGraphicsState.fTextLeading)));
+    SkPdfNumber* zero = pdfContext->fPdfDoc->createNumber(0.0);
+    SkPdfNumber* tl = pdfContext->fPdfDoc->createNumber(pdfContext->fGraphicsState.fTextLeading);
 
-    pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &zero));
-    pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &tl));
-    return PdfOp_Td(pdfContext, canvas, looper);
+    pdfContext->fObjectStack.push(zero);
+    pdfContext->fObjectStack.push(tl);
+
+    PdfResult ret = PdfOp_Td(pdfContext, canvas, looper);
+
+    delete zero;  // TODO(edisonn): do not alocate and delete constants!
+    delete tl;
+
+    return ret;
 }
 
 PdfResult PdfOp_m(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
@@ -1525,25 +1186,12 @@
 
 #ifdef PDF_TRACE
     printf("font name: %s\n", fontName.c_str());
-    std::string str;
-    pdfContext->fGraphicsState.fResources->podofo()->ToString(str);
-    printf("Print Tf Resources: %s\n", str.c_str());
-    pdfContext->fGraphicsState.fResources->Font()->podofo()->ToString(str);
-    printf("Print Tf Resources/Font: %s\n", str.c_str());
 #endif
 
     SkPdfFontDictionary* fd = NULL;
     if (pdfContext->fGraphicsState.fResources->Font()) {
         SkPdfObject* objFont = pdfContext->fGraphicsState.fResources->Font()->get(fontName.c_str());
-        mapFontDictionary(*objFont, &fd);
-
-#ifdef PDF_TRACE
-        objFont->podofo()->ToString(str);
-        printf("Print Font loaded: %s\n", str.c_str());
-        fd->podofo()->ToString(str);
-        printf("Print Font loaded and resolved and upgraded: %s\n", str.c_str());
-#endif
-
+        objFont->doc()->mapper()->mapFontDictionary(objFont, &fd);
     }
 
     SkPdfFont* skfont = SkPdfFont::fontFromPdfDictionary(fd);
@@ -1638,7 +1286,7 @@
     return kPartial_PdfResult;  // TODO(edisonn): Implement fully DrawText before returing OK.
 }
 
-PdfResult PdfOp_CS_cs(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator* colorOperator) {
+PdfResult PdfOp_CS_cs(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
     colorOperator->fColorSpace = pdfContext->fObjectStack.top()->asName()->value();    pdfContext->fObjectStack.pop();
     return kOK_PdfResult;
 }
@@ -1651,7 +1299,7 @@
     return PdfOp_CS_cs(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking);
 }
 
-PdfResult PdfOp_SC_sc(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator* colorOperator) {
+PdfResult PdfOp_SC_sc(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
     double c[4];
     pdf_int64 v[4];
 
@@ -1668,9 +1316,9 @@
 
     for (int i = n - 1; i >= 0 ; i--) {
         if (doubles) {
-            c[i] = pdfContext->fObjectStack.top()->asNumber()->value();     pdfContext->fObjectStack.pop();
+            c[i] = pdfContext->fObjectStack.top()->asNumber()->value();         pdfContext->fObjectStack.pop();
         } else {
-            v[i] = pdfContext->fObjectStack.top()->asInteger()->value();   pdfContext->fObjectStack.pop();
+            v[i] = pdfContext->fObjectStack.top()->asInteger()->value();        pdfContext->fObjectStack.pop();
         }
     }
 
@@ -1689,7 +1337,7 @@
     return PdfOp_SC_sc(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking);
 }
 
-PdfResult PdfOp_SCN_scn(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator* colorOperator) {
+PdfResult PdfOp_SCN_scn(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
     PdfString name;
 
     if (pdfContext->fObjectStack.top()->asName()) {
@@ -1710,7 +1358,7 @@
     return PdfOp_SCN_scn(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking);
 }
 
-PdfResult PdfOp_G_g(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator* colorOperator) {
+PdfResult PdfOp_G_g(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
     double gray = pdfContext->fObjectStack.top()->asNumber()->value();     pdfContext->fObjectStack.pop();
     return kNYI_PdfResult;
 }
@@ -1723,7 +1371,7 @@
     return PdfOp_G_g(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking);
 }
 
-PdfResult PdfOp_RG_rg(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator* colorOperator) {
+PdfResult PdfOp_RG_rg(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
     double b = pdfContext->fObjectStack.top()->asNumber()->value();     pdfContext->fObjectStack.pop();
     double g = pdfContext->fObjectStack.top()->asNumber()->value();     pdfContext->fObjectStack.pop();
     double r = pdfContext->fObjectStack.top()->asNumber()->value();     pdfContext->fObjectStack.pop();
@@ -1741,7 +1389,7 @@
     return PdfOp_RG_rg(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking);
 }
 
-PdfResult PdfOp_K_k(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator* colorOperator) {
+PdfResult PdfOp_K_k(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) {
     // TODO(edisonn): spec has some rules about overprint, implement them.
     double k = pdfContext->fObjectStack.top()->asNumber()->value();     pdfContext->fObjectStack.pop();
     double y = pdfContext->fObjectStack.top()->asNumber()->value();     pdfContext->fObjectStack.pop();
@@ -1896,13 +1544,8 @@
 
     SkPdfObject* value = extGStateDictionary->get(name.c_str());
 
-#ifdef PDF_TRACE
-//    value->ToString(str);
-//    printf("gs object value: %s\n", str.c_str());
-#endif
-
     SkPdfGraphicsStateDictionary* gs = NULL;
-    mapGraphicsStateDictionary(*value, &gs);
+    value->doc()->mapper()->mapGraphicsStateDictionary(value, &gs);
 
     // TODO(edisonn): now load all those properties in graphic state.
     if (gs == NULL) {
@@ -2300,60 +1943,52 @@
 // references automatically.
 
 bool SkPdfViewer::load(const SkString inputFileName, SkPicture* out) {
-    try
+    std::cout << "Init: " << inputFileName.c_str() << std::endl;
+
+    SkPodofoParsedPDF* doc = new SkPodofoParsedPDF(inputFileName.c_str());
+    if (!doc->pages())
     {
-        std::cout << "Init: " << inputFileName.c_str() << std::endl;
-
-        SkPdfDoc doc(inputFileName.c_str());
-        if (!doc.pages())
-        {
-            std::cout << "ERROR: Empty Document" << inputFileName.c_str() << std::endl;
-            return false;
-        } else {
-
-            for (int pn = 0; pn < doc.pages(); ++pn) {
-                // TODO(edisonn): implement inheritance properties as per PDF spec
-                //SkRect rect = page->MediaBox();
-                SkRect rect = doc.MediaBox(pn);
-
-    #ifdef PDF_TRACE
-                printf("Page Width: %f, Page Height: %f\n", SkScalarToDouble(rect.width()), SkScalarToDouble(rect.height()));
-    #endif
-
-                // TODO(edisonn): page->GetCropBox(), page->GetTrimBox() ... how to use?
-
-                SkBitmap bitmap;
-    #ifdef PDF_DEBUG_3X
-                setup_bitmap(&bitmap, 3 * (int)SkScalarToDouble(rect.width()), 3 * (int)SkScalarToDouble(rect.height()));
-    #else
-                setup_bitmap(&bitmap, (int)SkScalarToDouble(rect.width()), (int)SkScalarToDouble(rect.height()));
-    #endif
-                SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (bitmap)));
-                SkCanvas canvas(device);
-
-                gDumpBitmap = &bitmap;
-
-                doc.drawPage(pn, &canvas);
-
-                SkString out;
-                if (doc.pages() > 1) {
-                    out.appendf("%s-%i.png", inputFileName.c_str(), pn);
-                } else {
-                    out = inputFileName;
-                    // .pdf -> .png
-                    out[out.size() - 2] = 'n';
-                    out[out.size() - 1] = 'g';
-                }
-                SkImageEncoder::EncodeFile(out.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
-            }
-            return true;
-        }
-    }
-    catch( PdfError & e )
-    {
-        e.PrintErrorMsg();
-        std::cout << "ERROR: PDF can't be parsed!" << inputFileName.c_str() << std::endl;
+        std::cout << "ERROR: Empty Document" << inputFileName.c_str() << std::endl;
         return false;
+    } else {
+
+        for (int pn = 0; pn < doc->pages(); ++pn) {
+            // TODO(edisonn): implement inheritance properties as per PDF spec
+            //SkRect rect = page->MediaBox();
+            SkRect rect = doc->MediaBox(pn);
+
+#ifdef PDF_TRACE
+            printf("Page Width: %f, Page Height: %f\n", SkScalarToDouble(rect.width()), SkScalarToDouble(rect.height()));
+#endif
+
+            // TODO(edisonn): page->GetCropBox(), page->GetTrimBox() ... how to use?
+
+            SkBitmap bitmap;
+#ifdef PDF_DEBUG_3X
+            setup_bitmap(&bitmap, 3 * (int)SkScalarToDouble(rect.width()), 3 * (int)SkScalarToDouble(rect.height()));
+#else
+            setup_bitmap(&bitmap, (int)SkScalarToDouble(rect.width()), (int)SkScalarToDouble(rect.height()));
+#endif
+            SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (bitmap)));
+            SkCanvas canvas(device);
+
+            gDumpBitmap = &bitmap;
+
+            gDumpCanvas = &canvas;
+            doc->drawPage(pn, &canvas);
+
+            SkString out;
+            if (doc->pages() > 1) {
+                out.appendf("%s-%i.png", inputFileName.c_str(), pn);
+            } else {
+                out = inputFileName;
+                // .pdf -> .png
+                out[out.size() - 2] = 'n';
+                out[out.size() - 1] = 'g';
+            }
+            SkImageEncoder::EncodeFile(out.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
+        }
+        return true;
     }
 
     return true;
diff --git a/experimental/PdfViewer/SkPdfParser.h b/experimental/PdfViewer/SkPdfParser.h
index c156004..5841b12 100644
--- a/experimental/PdfViewer/SkPdfParser.h
+++ b/experimental/PdfViewer/SkPdfParser.h
@@ -5,167 +5,30 @@
  * found in the LICENSE file.
  */
 
-#include "podofo.h"
 #include "SkPdfHeaders_autogen.h"
-#include "SkPdfPodofoMapper_autogen.h"
+#include "SkPdfMapper_autogen.h"
 
 #ifndef SkPdfParser_DEFINED
 #define SkPdfParser_DEFINED
 
-
-enum SkPdfTokenType {
-    kKeyword_TokenType,
-    kObject_TokenType,
-    kImageData_TokenType,  // TODO(edisonn): inline images seem to work without it
-};
-
-struct PdfToken {
-    const char*      fKeyword;
-    SkPdfObject*     fObject;
-    SkPdfTokenType   fType;
-
-    PdfToken() : fKeyword(NULL), fObject(NULL) {}
-};
-
-class SkPdfTokenizer {
-    PdfMemDocument* fDoc;
-    PdfContentsTokenizer* fTokenizer;
-
-    char* fUncompressedStream;
-    pdf_long fUncompressedStreamLength;
-
-    bool fEmpty;
-    bool fHasPutBack;
-    PdfToken fPutBack;
-
-public:
-    SkPdfTokenizer(PdfMemDocument* doc = NULL, PdfContentsTokenizer* tokenizer = NULL) : fDoc(doc), fTokenizer(tokenizer), fUncompressedStream(NULL), fUncompressedStreamLength(0),  fEmpty(false), fHasPutBack(false) {}
-    SkPdfTokenizer(const SkPdfObject* objWithStream) : fDoc(NULL), fTokenizer(NULL), fEmpty(false), fHasPutBack(false) {
-        fUncompressedStream = NULL;
-        fUncompressedStreamLength = 0;
-
-        fDoc = NULL;
-
-
-        try {
-            objWithStream->podofo()->GetStream()->GetFilteredCopy(&fUncompressedStream, &fUncompressedStreamLength);
-            if (fUncompressedStream != NULL && fUncompressedStreamLength != 0) {
-                fTokenizer = new PdfContentsTokenizer(fUncompressedStream, fUncompressedStreamLength);
-            } else {
-                fEmpty = true;
-            }
-        } catch (PdfError& e) {
-            fEmpty = true;
-        }
-
-    }
-
-    SkPdfTokenizer(const char* buffer, int len) : fDoc(NULL), fTokenizer(NULL), fUncompressedStream(NULL), fUncompressedStreamLength(0), fEmpty(false), fHasPutBack(false) {
-        try {
-            fTokenizer = new PdfContentsTokenizer(buffer, len);
-        } catch (PdfError& e) {
-            fEmpty = true;
-        }
-    }
-
-    ~SkPdfTokenizer() {
-        free(fUncompressedStream);
-    }
-
-    void PutBack(PdfToken token) {
-        SkASSERT(!fHasPutBack);
-        fHasPutBack = true;
-        fPutBack = token;
-    }
-
-    bool readToken(PdfToken* token) {
-        if (fHasPutBack) {
-            *token = fPutBack;
-            fHasPutBack = false;
-            return true;
-        }
-
-        if (fEmpty) {
-            return false;
-        }
-
-        PdfVariant var;
-        EPdfContentsType type;
-
-        token->fKeyword = NULL;
-        token->fObject = NULL;
-
-        bool ret = fTokenizer->ReadNext(type, token->fKeyword, var);
-
-        if (!ret) return ret;
-
-        switch (type) {
-            case ePdfContentsType_Keyword:
-                token->fType = kKeyword_TokenType;
-                break;
-
-            case ePdfContentsType_Variant: {
-                    token->fType = kObject_TokenType;
-                    PdfObject* obj = new PdfObject(var);
-                    mapObject(*fDoc, *obj, &token->fObject);
-                }
-                break;
-
-            case ePdfContentsType_ImageData:
-                token->fType = kImageData_TokenType;
-                // TODO(edisonn): inline images seem to work without it
-                break;
-        }
-#ifdef PDF_TRACE
-        std::string str;
-        if (token->fObject) {
-            token->fObject->podofo()->ToString(str);
-        }
-        printf("%s %s\n", token->fType == kKeyword_TokenType ? "Keyword" : token->fType == kObject_TokenType ? "Object" : "ImageData", token->fKeyword ? token->fKeyword : str.c_str());
-#endif
-        return ret;
-    }
-};
+#include "SkPdfBasics.h"
+#include "SkPdfPodofoTokenizer.h"
 
 extern "C" PdfContext* gPdfContext;
 extern "C" SkBitmap* gDumpBitmap;
 extern "C" SkCanvas* gDumpCanvas;
 
-// TODO(edisonn): move in trace util.
-#ifdef PDF_TRACE
-static void SkTraceMatrix(const SkMatrix& matrix, const char* sz = "") {
-    printf("SkMatrix %s ", sz);
-    for (int i = 0 ; i < 9 ; i++) {
-        printf("%f ", SkScalarToDouble(matrix.get(i)));
-    }
-    printf("\n");
-}
-
-static void SkTraceRect(const SkRect& rect, const char* sz = "") {
-    printf("SkRect %s ", sz);
-    printf("x = %f ", SkScalarToDouble(rect.x()));
-    printf("y = %f ", SkScalarToDouble(rect.y()));
-    printf("w = %f ", SkScalarToDouble(rect.width()));
-    printf("h = %f ", SkScalarToDouble(rect.height()));
-    printf("\n");
-}
-
-#else
-#define SkTraceMatrix(a,b)
-#define SkTraceRect(a,b)
-#endif
-
 // TODO(edisonn): Document PdfTokenLooper and subclasses.
 class PdfTokenLooper {
 protected:
     PdfTokenLooper* fParent;
-    SkPdfTokenizer* fTokenizer;
+    SkPdfPodofoTokenizer* fTokenizer;
     PdfContext* fPdfContext;
     SkCanvas* fCanvas;
 
 public:
     PdfTokenLooper(PdfTokenLooper* parent,
-                   SkPdfTokenizer* tokenizer,
+                   SkPdfPodofoTokenizer* tokenizer,
                    PdfContext* pdfContext,
                    SkCanvas* canvas)
         : fParent(parent), fTokenizer(tokenizer), fPdfContext(pdfContext), fCanvas(canvas) {}
@@ -184,7 +47,7 @@
 class PdfMainLooper : public PdfTokenLooper {
 public:
     PdfMainLooper(PdfTokenLooper* parent,
-                  SkPdfTokenizer* tokenizer,
+                  SkPdfPodofoTokenizer* tokenizer,
                   PdfContext* pdfContext,
                   SkCanvas* canvas)
         : PdfTokenLooper(parent, tokenizer, pdfContext, canvas) {}
@@ -212,119 +75,6 @@
     virtual void loop();
 };
 
-class SkPdfDoc {
-    PdfMemDocument fDoc;
-public:
-
-    PdfMemDocument& podofo() {return fDoc;}
-
-    SkPdfDoc(const char* path) : fDoc(path) {}
-
-    int pages() {
-        return fDoc.GetPageCount();
-    }
-
-    double width(int n) {
-        PdfRect rect = fDoc.GetPage(n)->GetMediaBox();
-        return rect.GetWidth() + rect.GetLeft();
-    }
-
-    double height(int n) {
-        PdfRect rect = fDoc.GetPage(n)->GetMediaBox();
-        return rect.GetHeight() + rect.GetBottom();
-    }
-
-    // Can return NULL
-    SkPdfPageObjectDictionary* page(int n) {
-        SkPdfPageObjectDictionary* page = NULL;
-        mapPageObjectDictionary(fDoc, *fDoc.GetPage(n)->GetObject(), &page);
-        return page;
-    }
-
-    SkRect MediaBox(int n) {
-        PdfRect rect = fDoc.GetPage(n)->GetMediaBox();
-        SkRect skrect = SkRect::MakeLTRB(SkDoubleToScalar(rect.GetLeft()),
-                                         SkDoubleToScalar(rect.GetBottom()),
-                                         SkDoubleToScalar(rect.GetLeft() + rect.GetWidth()),
-                                         SkDoubleToScalar(rect.GetBottom() + rect.GetHeight()));
-        return skrect;
-    }
-
-    void drawPage(int n, SkCanvas* canvas) {
-        SkPdfPageObjectDictionary* pg = page(n);
-        SkPdfTokenizer* tokenizer = tokenizerOfPage(n);
-
-        PdfContext pdfContext(this);
-        pdfContext.fOriginalMatrix = SkMatrix::I();
-        pdfContext.fGraphicsState.fResources = NULL;
-        mapResourceDictionary(*pg->Resources(), &pdfContext.fGraphicsState.fResources);
-
-        gPdfContext = &pdfContext;
-        gDumpCanvas = canvas;
-
-        // TODO(edisonn): get matrix stuff right.
-        // TODO(edisonn): add DPI/scale/zoom.
-        SkScalar z = SkIntToScalar(0);
-        SkRect rect = MediaBox(n);
-        SkScalar w = rect.width();
-        SkScalar h = rect.height();
-
-        SkPoint pdfSpace[4] = {SkPoint::Make(z, z), SkPoint::Make(w, z), SkPoint::Make(w, h), SkPoint::Make(z, h)};
-//                SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoint::Make(w, z), SkPoint::Make(z, z)};
-
-        // TODO(edisonn): add flag for this app to create sourunding buffer zone
-        // TODO(edisonn): add flagg for no clipping.
-        // Use larger image to make sure we do not draw anything outside of page
-        // could be used in tests.
-
-#ifdef PDF_DEBUG_3X
-        SkPoint skiaSpace[4] = {SkPoint::Make(w+z, h+h), SkPoint::Make(w+w, h+h), SkPoint::Make(w+w, h+z), SkPoint::Make(w+z, h+z)};
-#else
-        SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoint::Make(w, z), SkPoint::Make(z, z)};
-#endif
-        //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(w, h)};
-        //SkPoint skiaSpace[2] = {SkPoint::Make(w, z), SkPoint::Make(z, h)};
-
-        //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(z, h)};
-        //SkPoint skiaSpace[2] = {SkPoint::Make(z, h), SkPoint::Make(z, z)};
-
-        //SkPoint pdfSpace[3] = {SkPoint::Make(z, z), SkPoint::Make(z, h), SkPoint::Make(w, h)};
-        //SkPoint skiaSpace[3] = {SkPoint::Make(z, h), SkPoint::Make(z, z), SkPoint::Make(w, 0)};
-
-        SkAssertResult(pdfContext.fOriginalMatrix.setPolyToPoly(pdfSpace, skiaSpace, 4));
-        SkTraceMatrix(pdfContext.fOriginalMatrix, "Original matrix");
-
-
-        pdfContext.fGraphicsState.fMatrix = pdfContext.fOriginalMatrix;
-        pdfContext.fGraphicsState.fMatrixTm = pdfContext.fGraphicsState.fMatrix;
-        pdfContext.fGraphicsState.fMatrixTlm = pdfContext.fGraphicsState.fMatrix;
-
-        canvas->setMatrix(pdfContext.fOriginalMatrix);
-
-#ifndef PDF_DEBUG_NO_PAGE_CLIPING
-        canvas->clipRect(SkRect::MakeXYWH(z, z, w, h), SkRegion::kIntersect_Op, true);
-#endif
-
-// erase with red before?
-//        SkPaint paint;
-//        paint.setColor(SK_ColorRED);
-//        canvas->drawRect(rect, paint);
-
-        PdfMainLooper looper(NULL, tokenizer, &pdfContext, canvas);
-        looper.loop();
-
-        delete tokenizer;
-
-
-        canvas->flush();
-    }
-
-    SkPdfTokenizer* tokenizerOfPage(int n) {
-        PdfContentsTokenizer* t = new PdfContentsTokenizer(fDoc.GetPage(n));
-        return new SkPdfTokenizer(&fDoc, t);
-    }
-};
-
 // TODO(edisonn): move in another file
 class SkPdfViewer : public SkRefCnt {
 public:
diff --git a/experimental/PdfViewer/SkPdfUtils.cpp b/experimental/PdfViewer/SkPdfUtils.cpp
index 29e3548..507077f 100644
--- a/experimental/PdfViewer/SkPdfUtils.cpp
+++ b/experimental/PdfViewer/SkPdfUtils.cpp
@@ -1,37 +1,2 @@
 #include "SkPdfUtils.h"
 
-bool ArrayFromDictionary(const PdfMemDocument* pdfDoc,
-                         const PdfDictionary& dict,
-                         const char* key,
-                         const char* abr,
-                         SkPdfArray* data) {return false;}
-
-bool FileSpecFromDictionary(const PdfMemDocument* pdfDoc,
-                         const PdfDictionary& dict,
-                         const char* key,
-                         const char* abr,
-                         SkPdfFileSpec* data) {return false;}
-
-bool StreamFromDictionary(const PdfMemDocument* pdfDoc,
-                         const PdfDictionary& dict,
-                         const char* key,
-                         const char* abr,
-                         SkPdfStream** data);
-
-bool TreeFromDictionary(const PdfMemDocument* pdfDoc,
-                         const PdfDictionary& dict,
-                         const char* key,
-                         const char* abr,
-                         SkPdfTree** data) {return false;}
-
-bool DateFromDictionary(const PdfMemDocument* pdfDoc,
-                         const PdfDictionary& dict,
-                         const char* key,
-                         const char* abr,
-                         SkPdfDate* data) {return false;}
-
-bool FunctionFromDictionary(const PdfMemDocument* pdfDoc,
-                         const PdfDictionary& dict,
-                         const char* key,
-                         const char* abr,
-                         SkPdfFunction* data) {return false;}
diff --git a/experimental/PdfViewer/SkPdfUtils.h b/experimental/PdfViewer/SkPdfUtils.h
index 858ab8e..03aacf6 100644
--- a/experimental/PdfViewer/SkPdfUtils.h
+++ b/experimental/PdfViewer/SkPdfUtils.h
@@ -1,124 +1,12 @@
 #ifndef __DEFINED__SkPdfUtils
 #define __DEFINED__SkPdfUtils
 
-#include "podofo.h"
-using namespace PoDoFo;
-
 #include "SkPdfBasics.h"
 
-const PdfObject* resolveReferenceObject(const PdfMemDocument* pdfDoc,
-                                  const PdfObject* obj,
-                                  bool resolveOneElementArrays = false);
-
-bool LongFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        long* data);
-
-bool DoubleFromDictionary(const PdfMemDocument* pdfDoc,
-                          const PdfDictionary& dict,
-                          const char* key,
-                          const char* abr,
-                          double* data);
-
-bool BoolFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        bool* data);
-
-bool NameFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        std::string* data);
-
-bool StringFromDictionary(const PdfMemDocument* pdfDoc,
-                          const PdfDictionary& dict,
-                          const char* key,
-                          const char* abr,
-                          std::string* data);
-/*
-class SkPdfDictionary;
-bool DictionaryFromDictionary(const PdfMemDocument* pdfDoc,
-                              const PdfDictionary& dict,
-                              const char* key,
-                              const char* abr,
-                              SkPdfDictionary** data);
-*/
-
-bool skpdfmap(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj, SkPdfObject** out);
-
-
-class SkPdfObject;
-bool ObjectFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkPdfObject** data);
-
-
-struct SkPdfFileSpec {};
 class SkPdfArray;
-class SkPdfStream;
-struct SkPdfDate {};
-struct SkPdfTree {};
-struct SkPdfFunction {};
-
-bool ArrayFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkPdfArray** data);
-
-bool SkMatrixFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkMatrix** data);
-
-bool FileSpecFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkPdfFileSpec* data);
-
-
-bool StreamFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkPdfStream** data);
-
-bool TreeFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkPdfTree** data);
-
-bool DateFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkPdfDate* data);
-
-bool SkRectFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkRect** data);
-
-bool FunctionFromDictionary(const PdfMemDocument* pdfDoc,
-                        const PdfDictionary& dict,
-                        const char* key,
-                        const char* abr,
-                        SkPdfFunction* data);
 
 SkMatrix SkMatrixFromPdfArray(SkPdfArray* pdfArray);
 
 PdfResult doType3Char(PdfContext* pdfContext, SkCanvas* canvas, SkPdfObject* skobj, SkRect bBox, SkMatrix matrix, double textSize);
 
-#include "SkPdfPodofoMapper_autogen.h"
-
 #endif   // __DEFINED__SkPdfUtils
diff --git a/experimental/PdfViewer/autogen.sh b/experimental/PdfViewer/autogen.sh
new file mode 100755
index 0000000..a1dcf67
--- /dev/null
+++ b/experimental/PdfViewer/autogen.sh
@@ -0,0 +1,5 @@
+rm pdfparser/autogen/*
+rm pdfparser/native/autogen/*
+rm pdfparser/podofo/autogen/*
+#python spec2def.py PdfReference-okular-1.txt autogen/pdfspec_autogen.py
+#python generate_code.py 'pdfparser/'
diff --git a/experimental/PdfViewer/autogen/__init__.py b/experimental/PdfViewer/autogen/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/experimental/PdfViewer/autogen/__init__.py
diff --git a/experimental/PdfViewer/generate_code.py b/experimental/PdfViewer/generate_code.py
index 69e06b6..baefab3 100644
--- a/experimental/PdfViewer/generate_code.py
+++ b/experimental/PdfViewer/generate_code.py
@@ -6,25 +6,25 @@
 from autogen.pdfspec_autogen import *
 
 knowTypes = {
-'(any)': ['SkPdfObject*', 'ObjectFromDictionary', datatypes.CppNull(), 'true'],
-'(undefined)': ['SkPdfObject*', 'ObjectFromDictionary', datatypes.CppNull(), 'true'],
-'(various)': ['SkPdfObject*', 'ObjectFromDictionary', datatypes.CppNull(), 'true'],
-'array': ['SkPdfArray*', 'ArrayFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == ePdfDataType_Array'],
-'boolean': ['bool', 'BoolFromDictionary', datatypes.PdfBoolean('false'), 'ret->podofo()->GetDataType() == ePdfDataType_Bool'],
-'date': ['SkPdfDate', 'DateFromDictionary', datatypes.PdfDateNever(), 'ret->podofo()->GetDataType() == ePdfDataType_Array'],
-'dictionary': ['SkPdfDictionary*', 'DictionaryFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == ePdfDataType_Dictionary'],
-'function': ['SkPdfFunction', 'FunctionFromDictionary', datatypes.PdfFunctionNone(), 'ret->podofo()->GetDataType() == ePdfDataType_Reference'],
-'integer': ['long', 'LongFromDictionary', datatypes.PdfInteger(0), 'ret->podofo()->GetDataType() == ePdfDataType_Number'],
-'file_specification': ['SkPdfFileSpec', 'FileSpecFromDictionary', datatypes.FileSpecNone(), 'ret->podofo()->GetDataType() == ePdfDataType_Reference'],
-'name': ['std::string', 'NameFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == ePdfDataType_Name'],
-'tree': ['SkPdfTree*', 'TreeFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == ePdfDataType_Reference'],
-'number': ['double', 'DoubleFromDictionary', datatypes.PdfNumber(0), 'ret->podofo()->GetDataType() == ePdfDataType_Real || ret->podofo()->GetDataType() == ePdfDataType_Number'],
-'rectangle': ['SkRect*', 'SkRectFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == ePdfDataType_Array && ret->podofo()->GetArray().GetLength() == 4'],
+'(any)': ['SkPdfObject*', 'SkPdfObjectFromDictionary', datatypes.CppNull(), 'true', 'use a mapper'],
+'(undefined)': ['SkPdfObject*', 'SkPdfObjectFromDictionary', datatypes.CppNull(), 'true', 'use a mapper'],
+'(various)': ['SkPdfObject*', 'SkPdfObjectFromDictionary', datatypes.CppNull(), 'true', 'use a mapper'],
+'array': ['SkPdfArray*', 'ArrayFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Array'],
+'boolean': ['bool', 'BoolFromDictionary', datatypes.PdfBoolean('false'), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Bool'],
+'date': ['SkPdfDate', 'DateFromDictionary', datatypes.PdfDateNever(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Array'],
+'dictionary': ['SkPdfDictionary*', 'SkPdfDictionaryFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Dictionary', 'use a mapper'],
+'function': ['SkPdfFunction', 'FunctionFromDictionary', datatypes.PdfFunctionNone(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Reference'],
+'integer': ['long', 'LongFromDictionary', datatypes.PdfInteger(0), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Number'],
+'file_specification': ['SkPdfFileSpec', 'FileSpecFromDictionary', datatypes.FileSpecNone(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Reference'],
+'name': ['std::string', 'NameFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Name'],
+'tree': ['SkPdfTree*', 'TreeFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Reference'],
+'number': ['double', 'DoubleFromDictionary', datatypes.PdfNumber(0), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Real || ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Number'],
+'rectangle': ['SkRect*', 'SkRectFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Array && ret->podofo()->GetArray().GetLength() == 4'],
 'stream': ['SkPdfStream*', 'StreamFromDictionary',  datatypes.CppNull(), 'ret->podofo()->HasStream()'],
-'string': ['std::string', 'StringFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == ePdfDataType_String || ret->podofo()->GetDataType() == ePdfDataType_HexString'],
-'text': ['std::string', 'StringFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == ePdfDataType_String || ret->podofo()->GetDataType() == ePdfDataType_HexString'],
-'text string': ['std::string', 'StringFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == ePdfDataType_String || ret->podofo()->GetDataType() == ePdfDataType_HexString'],
-'matrix': ['SkMatrix*', 'SkMatrixFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == ePdfDataType_Array && ret->podofo()->GetArray().GetLength() == 4'],
+'string': ['std::string', 'StringFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_String || ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_HexString'],
+'text': ['std::string', 'StringFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_String || ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_HexString'],
+'text string': ['std::string', 'StringFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_String || ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_HexString'],
+'matrix': ['SkMatrix*', 'SkMatrixFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Array && ret->podofo()->GetArray().GetLength() == 4'],
 }
 
 
@@ -101,8 +101,8 @@
   def __init__(self, name, base, comment):
     self.fFields = []
     self.fIncludes = []
-    self.fCCPublic = []
-    self.fCCPrivate = []
+    self.fCCPublicPodofo = []
+    self.fCCPublicPodofoCpp = []
     self.fName = name
     self.fBase = base
     self.fComment = comment
@@ -140,14 +140,14 @@
     self.fIncludes.append(path)
     return self
     
-  def carbonCopyPublic(self, cc):
-    self.fCCPublic.append(cc)
+  def carbonCopyPublicPodofo(self, cc):
+    self.fCCPublicPodofo.append(cc)
     return self 
 
-  def carbonCopyPrivate(self, cc):
-    self.fCCPrivate.append(cc)
+  def carbonCopyPublicPodofoCpp(self, cc):
+    self.fCCPublicPodofoCpp.append(cc)
     return self 
-    
+
   def done(self):
     return
 
@@ -179,40 +179,42 @@
        fileEnums.write('  ' + cls.fEnumEnd + ',\n')
 
 
-  def writeAsNull(self, fileClass, cls, enumToCls):
-    fileClass.write('  virtual SkPdf' + cls.fName +'* as' + cls.fName + '() {return NULL;}\n')
-    fileClass.write('  virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return NULL;}\n')
-    fileClass.write('\n')
+  def writeAsNull(self, podofoFileClass, cls, enumToCls):
+    podofoFileClass.write('  virtual SkPdf' + cls.fName +'* as' + cls.fName + '() {return NULL;}\n')
+    podofoFileClass.write('   virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return NULL;}\n')
+    podofoFileClass.write('\n')
 
     cnt = 0
     for sub in cls.fEnumSubclasses:
-      self.writeAsNull(fileClass, enumToCls[cls.fEnumSubclasses[cnt]], enumToCls)
+      self.writeAsNull(podofoFileClass, enumToCls[cls.fEnumSubclasses[cnt]], enumToCls)
       cnt = cnt + 1
 
        
-  def writeAsFoo(self, fileClass, cls, enumToCls):
+  def writeAsFoo(self, podofoFileClass, cls, enumToCls):
     # TODO(edisonn): add a container, with sections, public, private, default, ...
     # the end code will be grouped
     
     # me
-    fileClass.write('public:\n')
-    fileClass.write('  virtual SkPdf' + cls.fName +'* as' + cls.fName + '() {return this;}\n')
-    fileClass.write('  virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return this;}\n')
-    fileClass.write('\n')
+    podofoFileClass.write('public:\n')
+
+    podofoFileClass.write('public:\n')
+    podofoFileClass.write('   SkPdf' + cls.fName +'* as' + cls.fName + '() {return this;}\n')
+    podofoFileClass.write('  virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return this;}\n')
+    podofoFileClass.write('\n')
 
     if cls.fName == 'Object':
       cnt = 0
       for sub in cls.fEnumSubclasses:
-        self.writeAsNull(fileClass, enumToCls[cls.fEnumSubclasses[cnt]], enumToCls)
+        self.writeAsNull(podofoFileClass, enumToCls[cls.fEnumSubclasses[cnt]], enumToCls)
         cnt = cnt + 1
             
     if cls.fName != 'Object':
-      fileClass.write('private:\n')
+      podofoFileClass.write('private:\n')
       base = self.fClasses[cls.fBase]
       cnt = 0
       for sub in base.fEnumSubclasses:
         if enumToCls[base.fEnumSubclasses[cnt]].fName != cls.fName:
-          self.writeAsNull(fileClass, enumToCls[base.fEnumSubclasses[cnt]], enumToCls)
+          self.writeAsNull(podofoFileClass, enumToCls[base.fEnumSubclasses[cnt]], enumToCls)
         cnt = cnt + 1
       
       
@@ -235,8 +237,8 @@
     return mustBe 
   
   def write(self):
-    global fileHeaders 
-    global fileHeadersCpp 
+    global fileHeadersPodofo 
+    global fileHeadersPodofoCpp 
     global knowTypes
   
     # generate enum
@@ -249,8 +251,8 @@
       cls.fEnum = 'k' + name + '_SkPdfObjectType'
       cls.fEnumEnd = 'k' + name + '__End_SkPdfObjectType'
 
-      fileHeaders.write('#include "SkPdf' + cls.fName + '_autogen.h"\n')
-      fileHeadersCpp.write('#include "SkPdf' + cls.fName + '_autogen.cpp"\n')
+      fileHeadersPodofo.write('#include "SkPdf' + cls.fName + '_autogen.h"\n')
+      fileHeadersPodofoCpp.write('#include "SkPdf' + cls.fName + '_autogen.cpp"\n')
             
       if cls.fBase != '':
         self.fClasses[cls.fBase].fEnumSubclasses.append(cls.fEnum)
@@ -267,7 +269,7 @@
     # write imports
     
     # write enums
-    fileEnums = open('SkPdfEnums_autogen.h', 'w')
+    fileEnums = open(sys.argv[1] + 'autogen/SkPdfEnums_autogen.h', 'w')
     fileEnums.write('#ifndef __DEFINED__SkPdfEnums\n')
     fileEnums.write('#define __DEFINED__SkPdfEnums\n')
     fileEnums.write('\n')
@@ -290,72 +292,93 @@
       cls = self.fClasses[name]
       enum = cls.fEnum
       
-      fileClass = open('SkPdf' + cls.fName + '_autogen.h', 'w')
-      fileClassCpp = open('SkPdf' + cls.fName + '_autogen.cpp', 'w')
-      fileClass.write('#ifndef __DEFINED__SkPdf' + cls.fName + '\n')
-      fileClass.write('#define __DEFINED__SkPdf' + cls.fName + '\n')
-      fileClass.write('\n')
+      podofoFileClass = open(sys.argv[1] + 'podofo/autogen/SkPdf' + cls.fName + '_autogen.h', 'w')
+      podofoFileClassCpp = open(sys.argv[1] + 'podofo/autogen/SkPdf' + cls.fName + '_autogen.cpp', 'w')
 
-      fileClassCpp.write('#include "SkPdf' + cls.fName + '_autogen.h"\n\n')
-      fileClass.write('#include "SkPdfUtils.h"\n')
-      fileClass.write('#include "SkPdfEnums_autogen.h"\n')
-      fileClass.write('#include "SkPdfArray_autogen.h"\n')
+      podofoFileClass.write('#ifndef __DEFINED__SkPdf' + cls.fName + '\n')
+      podofoFileClass.write('#define __DEFINED__SkPdf' + cls.fName + '\n')
+      podofoFileClass.write('\n')
+
+      podofoFileClassCpp.write('#include "SkPdf' + cls.fName + '_autogen.h"\n\n')
+      podofoFileClassCpp.write('#include "podofo.h"\n')
+      podofoFileClassCpp.write('#include "SkPodofoUtils.h"\n')
+      podofoFileClassCpp.write('#include "SkPdfMapper_autogen.h"\n')
+      podofoFileClassCpp.write('\n')
+
+      
+      if cls.fBase == '':
+        podofoFileClass.write('#include "stddef.h"\n')
+        podofoFileClass.write('#include <string>\n')
+        podofoFileClass.write('#include "SkPdfEnums_autogen.h"\n')
+        podofoFileClass.write('#include "SkPdfNYI.h"\n')
+        podofoFileClass.write('#include "SkPodofoUtils.h"\n')
+
       if cls.fBase != '':
-        fileClass.write('#include "SkPdf' + cls.fBase + '_autogen.h"\n')
-      fileClass.write('\n')
+        podofoFileClass.write('#include "SkPdf' + cls.fBase + '_autogen.h"\n')
+
+      if cls.fBase == '':
+        podofoFileClass.write('#include "SkPodofoParsedPDF.h"\n')
+
+      podofoFileClass.write('\n')
+      
+      if cls.fBase == '':
+        podofoFileClass.write('namespace PoDoFo {\n')
+        podofoFileClass.write('class PdfMemDocument;\n')
+        podofoFileClass.write('class PdfObject;\n')      
+        podofoFileClass.write('}\n')
       
       if cls.fComment != '':
-        fileClass.write('// ' + cls.fComment + '\n')
+        podofoFileClass.write('// ' + cls.fComment + '\n')
       
       if cls.fBase == '':
-        fileClass.write('class SkPdf' + cls.fName + ' {\n')
+        podofoFileClass.write('class SkPdf' + cls.fName + ' {\n')
       else:
-        fileClass.write('class SkPdf' + cls.fName + ' : public SkPdf' + cls.fBase + ' {\n')
+        podofoFileClass.write('class SkPdf' + cls.fName + ' : public SkPdf' + cls.fBase + ' {\n')
       
-      fileClass.write('public:\n')
-      fileClass.write('  virtual SkPdfObjectType getType() const { return ' + cls.fEnum + ';}\n')
+      podofoFileClass.write('public:\n')
+      podofoFileClass.write('  virtual SkPdfObjectType getType() const { return ' + cls.fEnum + ';}\n')
       if len(cls.fEnumSubclasses) == 0:
-        fileClass.write('  virtual SkPdfObjectType getTypeEnd() const { return (SkPdfObjectType)(' + cls.fEnum + ' + 1);}\n')
+        podofoFileClass.write('  virtual SkPdfObjectType getTypeEnd() const { return (SkPdfObjectType)(' + cls.fEnum + ' + 1);}\n')
       else:
-        fileClass.write('  virtual SkPdfObjectType getTypeEnd() const { return ' + cls.fEnumEnd + ';}\n')
+        podofoFileClass.write('  virtual SkPdfObjectType getTypeEnd() const { return ' + cls.fEnumEnd + ';}\n')
       
-      self.writeAsFoo(fileClass, cls, enumToCls)
+      self.writeAsFoo(podofoFileClass, cls, enumToCls)
       
-      fileClass.write('public:\n')
-      for cc in cls.fCCPublic:
-        fileClass.write('  ' + cc + '\n')
-    
-      fileClass.write('private:\n')
-      for cc in cls.fCCPrivate:
-        fileClass.write('  ' + cc + '\n')
+      podofoFileClass.write('public:\n')
+
+      for cc in cls.fCCPublicPodofo:
+        podofoFileClass.write('  ' + cc + '\n')
+      
+      for cc in cls.fCCPublicPodofoCpp:
+        podofoFileClassCpp.write(cc + '\n\n')
+
 
       if cls.fBase == '':
-        fileClass.write('protected:\n')
-        fileClass.write('  const PdfMemDocument* fPodofoDoc;\n')
-        fileClass.write('  const PdfObject* fPodofoObj;\n')
-        fileClass.write('\n')
-        fileClass.write('public:\n')
-        fileClass.write('  SkPdf' + cls.fName + '(const PdfMemDocument* podofoDoc = NULL, const PdfObject* podofoObj = NULL) : fPodofoDoc(podofoDoc), fPodofoObj(podofoObj) {}\n')
-        fileClass.write('  SkPdf' + cls.fName + '(const SkPdf' + cls.fName + '& from) : fPodofoDoc(from.fPodofoDoc), fPodofoObj(from.fPodofoObj) {}\n')
-        fileClass.write('\n')
-        fileClass.write('  const PdfMemDocument* doc() const { return fPodofoDoc;}\n')
-        fileClass.write('  const PdfObject* podofo() const { return fPodofoObj;}\n')
+        podofoFileClass.write('protected:\n')
+        podofoFileClass.write('  const PoDoFo::PdfMemDocument* fPodofoDoc;\n')
+        podofoFileClass.write('  const SkPodofoParsedPDF* fParsedDoc;\n')
+        podofoFileClass.write('  const PoDoFo::PdfObject* fPodofoObj;\n')
+        podofoFileClass.write('\n')
+        
+        podofoFileClass.write('public:\n')
+        
+        podofoFileClass.write('  SkPdf' + cls.fName + '(const SkPodofoParsedPDF* doc = NULL, const PoDoFo::PdfObject* podofoObj = NULL) : fPodofoDoc(doc->podofo()), fParsedDoc(doc), fPodofoObj(podofoObj) {}\n')
+        podofoFileClass.write('\n')
+        podofoFileClass.write('  const SkPodofoParsedPDF* doc() const { return fParsedDoc;}\n')
+        podofoFileClass.write('  const void* data() const {return fPodofoObj;}\n')
+        podofoFileClass.write('  const PoDoFo::PdfObject* podofo() const {return fPodofoObj;}\n')
       else:
-        fileClass.write('public:\n')
-        fileClass.write('  SkPdf' + cls.fName + '(const PdfMemDocument* podofoDoc = NULL, const PdfObject* podofoObj = NULL) : SkPdf' + cls.fBase + '(podofoDoc, podofoObj) {}\n')
-        fileClass.write('\n')
-        fileClass.write('  SkPdf' + cls.fName + '(const SkPdf' + cls.fName + '& from) : SkPdf' + cls.fBase + '(from.fPodofoDoc, from.fPodofoObj) {}\n')
-        fileClass.write('\n')
+        podofoFileClass.write('public:\n')
+        podofoFileClass.write('  SkPdf' + cls.fName + '(const SkPodofoParsedPDF* doc = NULL, const PoDoFo::PdfObject* podofoObj = NULL) : SkPdf' + cls.fBase + '(doc, podofoObj) {}\n')
+        podofoFileClass.write('\n')
       
-      
+
+      # TODO(edisonn): add is valid ?
       #check required fieds, also, there should be an internal_valid() manually wrote for complex
       # situations
       # right now valid return true      
-      fileClass.write('  virtual bool valid() const {return true;}\n')
-      fileClass.write('\n')
-      
-      fileClass.write('  SkPdf' + cls.fName + '& operator=(const SkPdf' + cls.fName + '& from) {this->fPodofoDoc = from.fPodofoDoc; this->fPodofoObj = from.fPodofoObj; return *this;}\n')
-      fileClass.write('\n')
+      #podofoFileClass.write('  virtual bool valid() const {return true;}\n')
+      #podofoFileClass.write('\n')
       
       for field in cls.fFields:
         prop = field.fProp
@@ -363,98 +386,133 @@
           
           lines = prop.fComment.split('\n')
           if prop.fComment != '' and len(lines) > 0:
-            fileClass.write('/** ' + lines[0] + '\n')
+            podofoFileClass.write('/** ' + lines[0] + '\n')
             for line in lines[1:]:
-              fileClass.write(' *  ' + line + '\n')
-            fileClass.write('**/\n')
+              podofoFileClass.write(' *  ' + line + '\n')
+            podofoFileClass.write('**/\n')
           
           if prop.fCppName[0] == '[':
-            fileClass.write('/*\n')  # comment code of the atributes that can have any name
-            fileClassCpp.write('/*\n')  # comment code of the atributes that can have any name
+            podofoFileClass.write('/*\n')  # comment code of the atributes that can have any name
+            podofoFileClassCpp.write('/*\n')  # comment code of the atributes that can have any name
           
-          # TODO(edisonn): has_foo();  
-          fileClass.write('  bool has_' + prop.fCppName + '() const {\n')
-          fileClass.write('    return (ObjectFromDictionary(fPodofoDoc, fPodofoObj->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", NULL));\n')
-          fileClass.write('  }\n') 
-          fileClass.write('\n') 
 
           if len(prop.fTypes.split()) == 1:
             t = prop.fTypes.strip()
-            fileClass.write('  ' + knowTypes[t][0] + ' ' + prop.fCppName + '() const;\n')
-            fileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::' + prop.fCppName + '() const {\n')
-            fileClassCpp.write('  ' + knowTypes[t][0] + ' ret;\n')
-            fileClassCpp.write('  if (' + knowTypes[t][1] + '(fPodofoDoc, fPodofoObj->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;\n')
-            if field.fRequired == False and prop.fDefault != '':
-              fileClassCpp.write('  return ' + prop.fDefault.toCpp() + ';\n');
+
+            podofoFileClass.write('  ' + knowTypes[t][0] + ' ' + prop.fCppName + '() const;\n')
+            podofoFileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::' + prop.fCppName + '() const {\n')
+            podofoFileClassCpp.write('  ' + knowTypes[t][0] + ' ret;\n')
+            
+            #hack, find out if it is dict, they have an extra entry in the array
+            if len(knowTypes[t]) == 5:
+              podofoFileClassCpp.write('  if (fParsedDoc->mapper()->' + knowTypes[t][1] + '(podofo()->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;\n')
             else:
-              fileClassCpp.write('  // TODO(edisonn): warn about missing required field, assert for known good pdfs\n')
-              fileClassCpp.write('  return ' + knowTypes[t][2].toCpp() + ';\n');
-            fileClassCpp.write('}\n') 
-            fileClassCpp.write('\n')
+              podofoFileClassCpp.write('  if (' + knowTypes[t][1] + '(fParsedDoc, podofo()->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;\n')
+            
+            if field.fRequired == False and prop.fDefault != '':
+              podofoFileClassCpp.write('  return ' + prop.fDefault.toCpp() + ';\n');
+            else:
+              podofoFileClassCpp.write('  // TODO(edisonn): warn about missing required field, assert for known good pdfs\n')
+              podofoFileClassCpp.write('  return ' + knowTypes[t][2].toCpp() + ';\n');
+            podofoFileClassCpp.write('}\n') 
+            podofoFileClassCpp.write('\n')
           else:
             for type in prop.fTypes.split():
               t = type.strip()
-              fileClass.write('  bool is' + prop.fCppName + 'A' + t.title() + '() const {\n')
-              fileClass.write('    SkPdfObject* ret = NULL;\n')
-              fileClass.write('    if (!ObjectFromDictionary(fPodofoDoc, fPodofoObj->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return false;\n')
-              fileClass.write('    return ' + knowTypes[t][3] + ';\n')
-              fileClass.write('  }\n')
-              fileClass.write('\n')
+              
+              podofoFileClass.write('  bool is' + prop.fCppName + 'A' + t.title() + '() const;\n')
 
-              fileClass.write('  ' + knowTypes[t][0] + ' get' + prop.fCppName + 'As' + t.title() + '() const;\n')
-              fileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::get' + prop.fCppName + 'As' + t.title() + '() const {\n')
-              fileClassCpp.write('  ' + knowTypes[t][0] + ' ret = ' + knowTypes[t][2].toCpp() + ';\n')
-              fileClassCpp.write('  if (' + knowTypes[t][1] + '(fPodofoDoc, fPodofoObj->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;\n')
-              fileClassCpp.write('  // TODO(edisonn): warn about missing required field, assert for known good pdfs\n')
-              fileClassCpp.write('  return ' + knowTypes[t][2].toCpp() + ';\n')
-              fileClassCpp.write('}\n') 
-              fileClassCpp.write('\n')
+              podofoFileClassCpp.write('bool SkPdf' + cls.fName + '::is' + prop.fCppName + 'A' + t.title() + '() const {\n')
+              podofoFileClassCpp.write('  SkPdfObject* ret = NULL;\n')
+              podofoFileClassCpp.write('  if (!fParsedDoc->mapper()->SkPdfObjectFromDictionary(podofo()->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return false;\n')
+              podofoFileClassCpp.write('  return ' + knowTypes[t][3] + ';\n')
+              podofoFileClassCpp.write('}\n')
+              podofoFileClassCpp.write('\n')
+
+              podofoFileClass.write('  ' + knowTypes[t][0] + ' get' + prop.fCppName + 'As' + t.title() + '() const;\n')
+              podofoFileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::get' + prop.fCppName + 'As' + t.title() + '() const {\n')
+              podofoFileClassCpp.write('  ' + knowTypes[t][0] + ' ret = ' + knowTypes[t][2].toCpp() + ';\n')
+
+              # hack
+              if len(knowTypes[t]) == 5:
+                podofoFileClassCpp.write('  if (fParsedDoc->mapper()->' + knowTypes[t][1] + '(podofo()->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;\n')
+              else:
+                podofoFileClassCpp.write('  if (' + knowTypes[t][1] + '(fParsedDoc, podofo()->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;\n')
+              
+              podofoFileClassCpp.write('  // TODO(edisonn): warn about missing required field, assert for known good pdfs\n')
+              podofoFileClassCpp.write('  return ' + knowTypes[t][2].toCpp() + ';\n')
+              podofoFileClassCpp.write('}\n') 
+              podofoFileClassCpp.write('\n')
                
+          podofoFileClass.write('  bool has_' + prop.fCppName + '() const;\n')
+          podofoFileClassCpp.write('bool SkPdf' + cls.fName + '::has_' + prop.fCppName + '() const {\n')
+          podofoFileClassCpp.write('  return (ObjectFromDictionary(fParsedDoc, podofo()->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", NULL));\n')
+          podofoFileClassCpp.write('}\n') 
+          podofoFileClassCpp.write('\n') 
            
           if prop.fCppName[0] == '[':
-            fileClass.write('*/\n')  # comment code of the atributes that can have any name
-            fileClassCpp.write('*/\n')  # comment code of the atributes that can have any name
+            podofoFileClass.write('*/\n')  # comment code of the atributes that can have any name
+            podofoFileClassCpp.write('*/\n')  # comment code of the atributes that can have any name
          
 
-      fileClass.write('};\n')
-      fileClass.write('\n')
+      podofoFileClass.write('};\n')
+      podofoFileClass.write('\n')
 
-      fileClass.write('#endif  // __DEFINED__SkPdf' + cls.fName + '\n')
-      fileClass.close()
-      fileClassCpp.close()
-    
-      
+      podofoFileClass.write('#endif  // __DEFINED__PODOFO_SkPdf' + cls.fName + '\n')
+
+      podofoFileClass.close()
+      podofoFileClassCpp.close()
     
       # generate constructor when knowing the type
       # later, p2, generate constructor when not knowing the type - very similar with parsing?
       
     # generate parser  
     # TODO(edisonn): fast recognition based on must attributes.
-    fileMapper = open('SkPdfPodofoMapper_autogen.h', 'w')
-    fileMapperCpp = open('SkPdfPodofoMapper_autogen.cpp', 'w')
-    fileMapper.write('#ifndef __DEFINED__SkPdfPodofoMapper\n')
-    fileMapper.write('#define __DEFINED__SkPdfPodofoMapper\n')
-    fileMapper.write('\n')
+    fileMapperPodofo = open(sys.argv[1] + 'podofo/autogen/SkPdfMapper_autogen.h', 'w')
+    fileMapperPodofoCpp = open(sys.argv[1] + 'podofo/autogen/SkPdfMapper_autogen.cpp', 'w')
 
-    fileMapper.write('#include "SkPdfHeaders_autogen.h"\n')
-    fileMapperCpp.write('#include "SkPdfPodofoMapper_autogen.h"\n')
-#    fileMapper.write('class PodofoMapper {\n')
-#    fileMapper.write('public:\n')
+    fileMapperPodofo.write('#ifndef __DEFINED__SkPdfMapper\n')
+    fileMapperPodofo.write('#define __DEFINED__SkPdfMapper\n')
+    fileMapperPodofo.write('\n')
+
+    fileMapperPodofo.write('#include "SkPdfHeaders_autogen.h"\n')
+
+
+    fileMapperPodofo.write('namespace PoDoFo {\n')
+    fileMapperPodofo.write('class PdfDictionary;\n')
+    fileMapperPodofo.write('class PdfMemDocument;\n')
+    fileMapperPodofo.write('class PdfObject;\n')      
+    fileMapperPodofo.write('}\n')
+
+    fileMapperPodofoCpp.write('#include "SkPdfMapper_autogen.h"\n')
+    fileMapperPodofoCpp.write('#include "SkPdfUtils.h"\n')
+    fileMapperPodofoCpp.write('#include "podofo.h"\n')
+    fileMapperPodofoCpp.write('\n')
+    
+    fileMapperPodofo.write('class SkPdfMapper {\n')
+
+    fileMapperPodofo.write('  const SkPodofoParsedPDF* fParsedDoc;\n')
+    fileMapperPodofo.write('  const PoDoFo::PdfMemDocument* fPodofoDoc;\n')
+    
+    fileMapperPodofo.write('public:\n')
+    
+    fileMapperPodofo.write('  SkPdfMapper(const SkPodofoParsedPDF* doc) : fParsedDoc(doc), fPodofoDoc(doc ? doc->podofo() : NULL) {}\n')
+    fileMapperPodofo.write('\n')
+    
     for name in self.fClassesNamesInOrder:
       cls = self.fClasses[name]
       
+      fileMapperPodofo.write('  bool map' + name + '(const SkPdfObject* in, SkPdf' + name + '** out) const;\n')
 
-      fileMapper.write('bool map' + name + '(const SkPdfObject& in, SkPdf' + name + '** out);\n')
+      fileMapperPodofoCpp.write('bool SkPdfMapper::map' + name + '(const SkPdfObject* in, SkPdf' + name + '** out) const {\n')
+      fileMapperPodofoCpp.write('  return map' + name + '((const PoDoFo::PdfObject*)in->data(), (SkPdf' + name + '**)out);\n')
+      fileMapperPodofoCpp.write('}\n') 
+      fileMapperPodofoCpp.write('\n')
 
-      fileMapperCpp.write('bool map' + name + '(const SkPdfObject& in, SkPdf' + name + '** out) {\n')
-      fileMapperCpp.write('  return map' + name + '(*in.doc(), *in.podofo(), out);\n')
-      fileMapperCpp.write('}\n') 
-      fileMapperCpp.write('\n')
-
-      fileMapper.write('bool map' + name + '(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj, SkPdf' + name + '** out);\n')
-      fileMapperCpp.write('bool map' + name + '(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj, SkPdf' + name + '** out) {\n')
-      fileMapperCpp.write('  if (!is' + name + '(podofoDoc, podofoObj)) return false;\n')
-      fileMapperCpp.write('\n')
+      fileMapperPodofo.write('  bool map' + name + '(const PoDoFo::PdfObject* podofoObj, SkPdf' + name + '** out) const ;\n')
+      fileMapperPodofoCpp.write('bool SkPdfMapper::map' + name + '(const PoDoFo::PdfObject* podofoObj, SkPdf' + name + '** out) const {\n')
+      fileMapperPodofoCpp.write('  if (!is' + name + '(podofoObj)) return false;\n')
+      fileMapperPodofoCpp.write('\n')
 
       # stream must be last one
       hasStream = False
@@ -462,36 +520,36 @@
         if cls.fName == 'Object' and enumToCls[sub].fName == 'Stream':
           hasStream = True
         else:
-          fileMapperCpp.write('  if (map' + enumToCls[sub].fName + '(podofoDoc, podofoObj, (SkPdf' + enumToCls[sub].fName + '**)out)) return true;\n')
+          fileMapperPodofoCpp.write('  if (map' + enumToCls[sub].fName + '(podofoObj, (SkPdf' + enumToCls[sub].fName + '**)out)) return true;\n')
       
       if hasStream:
-        fileMapperCpp.write('  if (mapStream(podofoDoc, podofoObj, (SkPdfStream**)out)) return true;\n')
+        fileMapperPodofoCpp.write('  if (mapStream(podofoObj, (SkPdfStream**)out)) return true;\n')
       
 
-      fileMapperCpp.write('\n')
+      fileMapperPodofoCpp.write('\n')
       
-      fileMapperCpp.write('  *out = new SkPdf' + name + '(&podofoDoc, &podofoObj);\n')
-      fileMapperCpp.write('  return true;\n')        
-      fileMapperCpp.write('}\n') 
-      fileMapperCpp.write('\n')
+      fileMapperPodofoCpp.write('  *out = new SkPdf' + name + '(fParsedDoc, podofoObj);\n')
+      fileMapperPodofoCpp.write('  return true;\n')        
+      fileMapperPodofoCpp.write('}\n') 
+      fileMapperPodofoCpp.write('\n')
        
     for name in self.fClassesNamesInOrder:
       cls = self.fClasses[name]
       
-      fileMapper.write('bool is' + name + '(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj);\n')
-      fileMapperCpp.write('bool is' + name + '(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj) {\n')
+      fileMapperPodofo.write('  bool is' + name + '(const PoDoFo::PdfObject* podofoObj) const ;\n')
+      fileMapperPodofoCpp.write('bool SkPdfMapper::is' + name + '(const PoDoFo::PdfObject* podofoObj) const {\n')
       
       if cls.fCheck != '':
-        fileMapperCpp.write('  return ' + cls.fCheck + ';\n')
+        fileMapperPodofoCpp.write('  return ' + cls.fCheck + ';\n')
       else:
         cntMust = 0
         for field in cls.fFields:
           prop = field.fProp
           if prop.fHasMust:
             cntMust = cntMust + 1
-            fileMapperCpp.write('  ' + knowTypes[prop.fTypes.strip()][0] + ' ' + prop.fCppName + ';\n')
-            fileMapperCpp.write('  if (!podofoObj.IsDictionary()) return false;\n')
-            fileMapperCpp.write('  if (!' + knowTypes[prop.fTypes.strip()][1] + '(&podofoDoc, podofoObj.GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &' + prop.fCppName + ')) return false;\n')
+            fileMapperPodofoCpp.write('  ' + knowTypes[prop.fTypes.strip()][0] + ' ' + prop.fCppName + ';\n')
+            fileMapperPodofoCpp.write('  if (!podofoObj->IsDictionary()) return false;\n')
+            fileMapperPodofoCpp.write('  if (!' + knowTypes[prop.fTypes.strip()][1] + '(fParsedDoc, podofoObj->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &' + prop.fCppName + ')) return false;\n')
             
             eval = '';
             # TODO(edisonn): this could get out of hand, and could have poor performance if continued on this path
@@ -505,88 +563,105 @@
                   eval = '(' + prop.fCppName + ' != ' + cnd.toCpp() + ')'
                 else:
                   eval = eval + ' && ' + '(' + prop.fCppName + ' != ' + cnd.toCpp() + ')'
-              fileMapperCpp.write('  if (' + eval + ') return false;\n')
-              fileMapperCpp.write('\n')
+              fileMapperPodofoCpp.write('  if (' + eval + ') return false;\n')
+              fileMapperPodofoCpp.write('\n')
       
-        fileMapperCpp.write('  return true;\n')
+        fileMapperPodofoCpp.write('  return true;\n')
               
-      fileMapperCpp.write('}\n') 
-      fileMapperCpp.write('\n')    
+      fileMapperPodofoCpp.write('}\n') 
+      fileMapperPodofoCpp.write('\n')    
     
-      fileMapper.write('bool ' + name + 'FromDictionary(const PdfMemDocument* pdfDoc, const PdfDictionary& dict, const char* key, SkPdf' + name + '** data);\n')
-      fileMapperCpp.write('bool ' + name + 'FromDictionary(const PdfMemDocument* pdfDoc, const PdfDictionary& dict, const char* key, SkPdf' + name + '** data) {\n')
-      fileMapperCpp.write('  const PdfObject* value = resolveReferenceObject(pdfDoc, dict.GetKey(PdfName(key)), true);\n')
-      fileMapperCpp.write('  if (value == NULL) { return false; }\n')
-      fileMapperCpp.write('  if (data == NULL) { return true; }\n')
-      fileMapperCpp.write('  return map' + name + '(*pdfDoc, *value, (SkPdf' + name + '**)data);\n')
-      fileMapperCpp.write('}\n')
-      fileMapperCpp.write('\n')
+      fileMapperPodofo.write('  bool SkPdf' + name + 'FromDictionary(const PoDoFo::PdfDictionary& dict, const char* key, SkPdf' + name + '** data) const ;\n')
+      fileMapperPodofoCpp.write('bool SkPdfMapper::SkPdf' + name + 'FromDictionary(const PoDoFo::PdfDictionary& dict, const char* key, SkPdf' + name + '** data) const {\n')
+      fileMapperPodofoCpp.write('  const PoDoFo::PdfObject* value = resolveReferenceObject(fParsedDoc, dict.GetKey(PoDoFo::PdfName(key)), true);\n')
+      fileMapperPodofoCpp.write('  if (value == NULL) { return false; }\n')
+      fileMapperPodofoCpp.write('  if (data == NULL) { return true; }\n')
+      fileMapperPodofoCpp.write('  return map' + name + '(value, (SkPdf' + name + '**)data);\n')
+      fileMapperPodofoCpp.write('}\n')
+      fileMapperPodofoCpp.write('\n')
 
-      fileMapper.write('bool ' + name + 'FromDictionary(const PdfMemDocument* pdfDoc, const PdfDictionary& dict, const char* key, const char* abr, SkPdf' + name + '** data);\n')
-      fileMapperCpp.write('bool ' + name + 'FromDictionary(const PdfMemDocument* pdfDoc, const PdfDictionary& dict, const char* key, const char* abr, SkPdf' + name + '** data) {\n')
-      fileMapperCpp.write('  if (' + name + 'FromDictionary(pdfDoc, dict, key, data)) return true;\n')
-      fileMapperCpp.write('  if (abr == NULL || *abr == \'\\0\') return false;\n')
-      fileMapperCpp.write('  return ' + name + 'FromDictionary(pdfDoc, dict, abr, data);\n')
-      fileMapperCpp.write('}\n')
-      fileMapperCpp.write('\n')
+      fileMapperPodofo.write('  bool SkPdf' + name + 'FromDictionary(const PoDoFo::PdfDictionary& dict, const char* key, const char* abr, SkPdf' + name + '** data) const ;\n')
+      fileMapperPodofoCpp.write('bool SkPdfMapper::SkPdf' + name + 'FromDictionary(const PoDoFo::PdfDictionary& dict, const char* key, const char* abr, SkPdf' + name + '** data) const {\n')
+      fileMapperPodofoCpp.write('  if (SkPdf' + name + 'FromDictionary(dict, key, data)) return true;\n')
+      fileMapperPodofoCpp.write('  if (abr == NULL || *abr == \'\\0\') return false;\n')
+      fileMapperPodofoCpp.write('  return SkPdf' + name + 'FromDictionary(dict, abr, data);\n')
+      fileMapperPodofoCpp.write('}\n')
+      fileMapperPodofoCpp.write('\n')
           
-    #fileMapper.write('};\n') 
-    fileMapper.write('\n')
+    fileMapperPodofo.write('};\n') 
+    fileMapperPodofo.write('\n')
     
-    fileMapper.write('#endif  // __DEFINED__SkPdfPodofoMapper\n')
-    fileMapper.close()
+    fileMapperPodofo.write('#endif  // __DEFINED__SkPdfMapper\n')
+
+    fileMapperPodofo.close()
+    fileMapperPodofoCpp.close()
     
     return
 
 def generateCode():
-  global fileHeaders 
-  global fileHeadersCpp 
+  global fileHeadersPodofo 
+  global fileHeadersPodofoCpp 
   global knowTypes
 
-  fileHeaders = open('SkPdfHeaders_autogen.h', 'w')
-  fileHeadersCpp = open('SkPdfHeaders_autogen.cpp', 'w')
-  fileHeaders.write('#ifndef __DEFINED__SkPdfHeaders\n')
-  fileHeaders.write('#define __DEFINED__SkPdfHeaders\n')
-  fileHeaders.write('\n')
+  fileHeadersPodofo = open(sys.argv[1] + 'podofo/autogen/SkPdfHeaders_autogen.h', 'w')
+  fileHeadersPodofoCpp = open(sys.argv[1] + 'podofo/autogen/SkPdfHeaders_autogen.cpp', 'w')
   
-  fileHeaders.write('#include "SkPdfEnums_autogen.h"\n')
+  fileHeadersPodofo.write('#ifndef __DEFINED__SkPdfHeaders\n')
+  fileHeadersPodofo.write('#define __DEFINED__SkPdfHeaders\n')
+  fileHeadersPodofo.write('\n')
 
-  fileHeadersCpp.write('#include "SkPdfHeaders_autogen.h"\n')
+  fileHeadersPodofoCpp.write('#include "SkPdfHeaders_autogen.h"\n')
 
   manager = PdfClassManager()
   
   manager.addClass('Object')
   
-  manager.addClass('Null').check('podofoObj.GetDataType() == ePdfDataType_Null')
-  manager.addClass('Boolean').check('podofoObj.GetDataType() == ePdfDataType_Bool')\
-                             .carbonCopyPublic('bool value() const {return fPodofoObj->GetBool();}')
+  # TODO(edisonn): perf, instead of virtual functions, store data in field and reurn it.
+  # maybe in constructor load it, or laizy load it 
+  
+  manager.addClass('Null').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Null')
+  manager.addClass('Boolean').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Bool')\
+                             .carbonCopyPublicPodofo('bool value() const;')\
+                             .carbonCopyPublicPodofoCpp('bool SkPdfBoolean::value() const {return podofo()->GetBool();}')
                              
-  manager.addClass('Integer').check('podofoObj.GetDataType() == ePdfDataType_Number || podofoObj.GetDataType() == ePdfDataType_Real')\
-                             .carbonCopyPublic('long value() const {return fPodofoObj->GetNumber();}')
+  manager.addClass('Integer').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Number || podofoObj->GetDataType() == PoDoFo::ePdfDataType_Real')\
+                             .carbonCopyPublicPodofo('long value() const;')\
+                             .carbonCopyPublicPodofoCpp('long SkPdfInteger::value() const {return podofo()->GetNumber();}')
   
-  manager.addClass('Number', 'Integer').check('podofoObj.GetDataType() == ePdfDataType_Number || podofoObj.GetDataType() == ePdfDataType_Real')\
-                             .carbonCopyPublic('double value() const {return fPodofoObj->GetReal();}')
+  manager.addClass('Number', 'Integer').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Number || podofoObj->GetDataType() == PoDoFo::ePdfDataType_Real')\
+                             .carbonCopyPublicPodofo('double value() const;')\
+                             .carbonCopyPublicPodofoCpp('double SkPdfNumber::value() const {return podofo()->GetReal();}')\
   
-  manager.addClass('Name').check('podofoObj.GetDataType() == ePdfDataType_Name')\
-                             .carbonCopyPublic('const std::string& value() const {return fPodofoObj->GetName().GetName();}')
+  manager.addClass('Name').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Name')\
+                             .carbonCopyPublicPodofo('const std::string& value() const;')\
+                             .carbonCopyPublicPodofoCpp('const std::string& SkPdfName::value() const {return podofo()->GetName().GetName();}')
   
-  manager.addClass('Reference').check('podofoObj.GetDataType() == ePdfDataType_Reference')
+  manager.addClass('Reference').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Reference')
   
-  manager.addClass('Array').check('podofoObj.GetDataType() == ePdfDataType_Array')\
-                             .carbonCopyPublic('const int size() const {return fPodofoObj->GetArray().GetSize();}')\
-                             .carbonCopyPublic('SkPdfObject* operator[](int i) const { SkPdfObject* ret = NULL;  skpdfmap(*fPodofoDoc, fPodofoObj->GetArray()[i], &ret);  return ret; }')\
+  manager.addClass('Array').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Array')\
+                             .carbonCopyPublicPodofo('const int size() const;')\
+                             .carbonCopyPublicPodofoCpp('const int SkPdfArray::size() const {return podofo()->GetArray().GetSize();}')\
+                             .carbonCopyPublicPodofo('SkPdfObject* operator[](int i) const;')\
+                             .carbonCopyPublicPodofoCpp('SkPdfObject* SkPdfArray::operator[](int i) const { SkPdfObject* ret = NULL;  fParsedDoc->mapper()->mapObject(&podofo()->GetArray()[i], &ret);  return ret; }')
   
-  manager.addClass('String').check('podofoObj.GetDataType() == ePdfDataType_String || podofoObj.GetDataType() == ePdfDataType_HexString')\
-                             .carbonCopyPublic('const std::string& value() const {return fPodofoObj->GetString().GetStringUtf8();}')
+  manager.addClass('String').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_String || podofoObj->GetDataType() == PoDoFo::ePdfDataType_HexString')\
+                            .carbonCopyPublicPodofo('const std::string& value() const;')\
+                            .carbonCopyPublicPodofoCpp('const std::string& SkPdfString::value() const {return podofo()->GetString().GetStringUtf8();}')\
+                            .carbonCopyPublicPodofo('const char* c_str() const;')\
+                            .carbonCopyPublicPodofoCpp('const char* SkPdfString::c_str() const {return podofo()->GetString().GetString();}')\
+                            .carbonCopyPublicPodofo('size_t len() const;')\
+                            .carbonCopyPublicPodofoCpp('size_t SkPdfString::len() const {return podofo()->GetString().GetLength();}')
                              
-  manager.addClass('HexString', 'String').check('podofoObj.GetDataType() == ePdfDataType_HexString')\
-                             .carbonCopyPublic('const std::string& value() const {return fPodofoObj->GetString().GetStringUtf8();}')
+  manager.addClass('HexString', 'String').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_HexString')\
   
-  manager.addClass('Dictionary').check('podofoObj.GetDataType() == ePdfDataType_Dictionary')\
-                                .carbonCopyPublic('SkPdfObject* get(const char* dictionaryKeyName) const {return new SkPdfObject(fPodofoDoc, resolveReferenceObject(fPodofoDoc, fPodofoObj->GetDictionary().GetKey(PdfName(dictionaryKeyName))));}')\
-                                .carbonCopyPublic('SkPdfObject* get(const char* dictionaryKeyName) {return new SkPdfObject(fPodofoDoc, resolveReferenceObject(fPodofoDoc, fPodofoObj->GetDictionary().GetKey(PdfName(dictionaryKeyName))));}')\
+  manager.addClass('Dictionary').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Dictionary')\
+                                .carbonCopyPublicPodofo('SkPdfObject* get(const char* dictionaryKeyName) const;')\
+                                .carbonCopyPublicPodofoCpp('SkPdfObject* SkPdfDictionary::get(const char* dictionaryKeyName) const {SkPdfObject* ret = NULL; fParsedDoc->mapper()->mapObject(resolveReferenceObject(fParsedDoc, podofo()->GetDictionary().GetKey(PoDoFo::PdfName(dictionaryKeyName))), &ret); return ret;}')\
 
-  manager.addClass('Stream')  # attached to a dictionary in podofo
+  # attached to a dictionary in podofo
+  manager.addClass('Stream')\
+              .carbonCopyPublicPodofo('bool GetFilteredCopy(char** buffer, long* len) const;')\
+              .carbonCopyPublicPodofoCpp('bool SkPdfStream::GetFilteredCopy(char** buffer, long* len) const {try {PoDoFo::pdf_long podofoLen = 0; *buffer = NULL; *len = 0;podofo()->GetStream()->GetFilteredCopy(buffer, &podofoLen); *len = (long)podofoLen;} catch (PoDoFo::PdfError& e) { return false; } return true;}')
   
   
   # these classes are not explicitely backed by a table in the pdf spec
@@ -619,12 +694,12 @@
 
   manager.write()
   
-  fileHeaders.write('#endif  // __DEFINED__SkPdfHeaders\n')
-  fileHeaders.close()
-  fileHeadersCpp.close()
-  
-  return 1
+  fileHeadersPodofo.write('#endif  // __DEFINED__SkPdfHeaders\n')
+
+  fileHeadersPodofo.close()
+  fileHeadersPodofoCpp.close()
 
 if '__main__' == __name__:
+  #print sys.argv
   sys.exit(generateCode())
 
diff --git a/experimental/PdfViewer/pdfparser/SkPdfNYI.cpp b/experimental/PdfViewer/pdfparser/SkPdfNYI.cpp
new file mode 100644
index 0000000..7868cc6
--- /dev/null
+++ b/experimental/PdfViewer/pdfparser/SkPdfNYI.cpp
@@ -0,0 +1,4 @@
+
+#include "SkPdfNYI.h"
+
+
diff --git a/experimental/PdfViewer/pdfparser/SkPdfNYI.h b/experimental/PdfViewer/pdfparser/SkPdfNYI.h
new file mode 100644
index 0000000..5f1ee82
--- /dev/null
+++ b/experimental/PdfViewer/pdfparser/SkPdfNYI.h
@@ -0,0 +1,10 @@
+#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_SKPDFNYI_H_
+#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_SKPDFNYI_H_
+
+struct SkPdfFileSpec {};
+struct SkPdfDate {};
+struct SkPdfTree {};
+struct SkPdfFunction {};
+
+
+#endif  // EXPERIMENTAL_PDFVIEWER_PDFPARSER_SKPDFNYI_H_
diff --git a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp
new file mode 100644
index 0000000..f405d4a
--- /dev/null
+++ b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp
@@ -0,0 +1,12 @@
+
+#include "SkNativeParsedPDF.h"
+
+SkNativeParsedPDF::SkNativeParsedPDF() {
+    // TODO(edisonn): Auto-generated constructor stub
+
+}
+
+SkNativeParsedPDF::~SkNativeParsedPDF() {
+    // TODO(edisonn): Auto-generated destructor stub
+}
+
diff --git a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h
new file mode 100644
index 0000000..38c72b0
--- /dev/null
+++ b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h
@@ -0,0 +1,12 @@
+#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKNATIVEPARSEDPDF_H_
+#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKNATIVEPARSEDPDF_H_
+
+#include "base/macros.h"
+
+class SkNativeParsedPDF : public SkParsedPDF {
+public:
+    SkNativeParsedPDF();
+    virtual ~SkNativeParsedPDF();
+};
+
+#endif  // EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKNATIVEPARSEDPDF_H_
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
new file mode 100644
index 0000000..ea744ac
--- /dev/null
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
@@ -0,0 +1,12 @@
+
+#include "SkPdfNativeTokenizer.h"
+
+SkPdfNativeTokenizer::SkPdfNativeTokenizer() {
+    // TODO(edisonn): Auto-generated constructor stub
+
+}
+
+SkPdfNativeTokenizer::~SkPdfNativeTokenizer() {
+    // TODO(edisonn): Auto-generated destructor stub
+}
+
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h
new file mode 100644
index 0000000..c8a2f46
--- /dev/null
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h
@@ -0,0 +1,10 @@
+#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFNATIVETOKENIZER_H_
+#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFNATIVETOKENIZER_H_
+
+class SkPdfNativeTokenizer : public SkPdfPodofoTokenizer {
+public:
+    SkPdfNativeTokenizer();
+    virtual ~SkPdfNativeTokenizer();
+};
+
+#endif  // EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFNATIVETOKENIZER_H_
diff --git a/experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.cpp b/experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.cpp
new file mode 100644
index 0000000..3738253
--- /dev/null
+++ b/experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.cpp
@@ -0,0 +1,102 @@
+#include "SkPdfPodofoTokenizer.h"
+
+#include "SkTypes.h"
+#include "SkPdfStream_autogen.h"
+#include "SkPdfMapper_autogen.h"
+
+#include "podofo.h"
+
+// maps to a null doc, if the code asks for it, we should err/crash.
+SkPdfMapper gNullMapper(NULL);
+
+SkPdfPodofoTokenizer::SkPdfPodofoTokenizer(const SkPodofoParsedPDF* parser, PoDoFo::PdfContentsTokenizer* tokenizer)
+    : fMapper(parser->mapper()), fDoc(parser->podofo()), fTokenizer(tokenizer), fUncompressedStream(NULL), fUncompressedStreamLength(0), fEmpty(false), fHasPutBack(false) {}
+
+SkPdfPodofoTokenizer::SkPdfPodofoTokenizer(const SkPdfObject* objWithStream) : fMapper(&gNullMapper), fDoc(NULL), fTokenizer(NULL), fUncompressedStream(NULL), fUncompressedStreamLength(0), fEmpty(false), fHasPutBack(false) {
+    fUncompressedStream = NULL;
+    fUncompressedStreamLength = 0;
+
+    fDoc = NULL;
+
+    SkPdfStream* stream = NULL;
+    if (objWithStream &&
+            objWithStream->doc()->mapper()->mapStream(objWithStream, &stream) &&
+            stream->GetFilteredCopy(&fUncompressedStream, &fUncompressedStreamLength) &&
+            fUncompressedStream != NULL &&
+            fUncompressedStreamLength != 0) {
+        fTokenizer = new PoDoFo::PdfContentsTokenizer(fUncompressedStream, fUncompressedStreamLength);
+        fDoc = objWithStream->doc()->podofo();
+    } else {
+        fEmpty = true;
+    }
+}
+
+SkPdfPodofoTokenizer::SkPdfPodofoTokenizer(const char* buffer, int len) : fMapper(&gNullMapper), fDoc(NULL), fTokenizer(NULL), fUncompressedStream(NULL), fUncompressedStreamLength(0), fEmpty(false), fHasPutBack(false) {
+    try {
+        fTokenizer = new PoDoFo::PdfContentsTokenizer(buffer, len);
+    } catch (PoDoFo::PdfError& e) {
+        fEmpty = true;
+    }
+}
+
+SkPdfPodofoTokenizer::~SkPdfPodofoTokenizer() {
+    free(fUncompressedStream);
+}
+
+bool SkPdfPodofoTokenizer::readTokenCore(PdfToken* token) {
+    PoDoFo::PdfVariant var;
+    PoDoFo::EPdfContentsType type;
+
+    token->fKeyword = NULL;
+    token->fObject = NULL;
+
+    bool ret = fTokenizer->ReadNext(type, token->fKeyword, var);
+
+    if (!ret) return ret;
+
+    switch (type) {
+        case PoDoFo::ePdfContentsType_Keyword:
+            token->fType = kKeyword_TokenType;
+            break;
+
+        case PoDoFo::ePdfContentsType_Variant: {
+                token->fType = kObject_TokenType;
+                PoDoFo::PdfObject* obj = new PoDoFo::PdfObject(var);
+                fMapper->mapObject(obj, &token->fObject);
+            }
+            break;
+
+        case PoDoFo::ePdfContentsType_ImageData:
+            token->fType = kImageData_TokenType;
+            // TODO(edisonn): inline images seem to work without it
+            break;
+    }
+#ifdef PDF_TRACE
+    std::string str;
+    if (token->fObject) {
+        token->fObject->podofo()->ToString(str);
+    }
+    printf("%s %s\n", token->fType == kKeyword_TokenType ? "Keyword" : token->fType == kObject_TokenType ? "Object" : "ImageData", token->fKeyword ? token->fKeyword : str.c_str());
+#endif
+    return ret;
+}
+
+void SkPdfPodofoTokenizer::PutBack(PdfToken token) {
+    SkASSERT(!fHasPutBack);
+    fHasPutBack = true;
+    fPutBack = token;
+}
+
+bool SkPdfPodofoTokenizer::readToken(PdfToken* token) {
+    if (fHasPutBack) {
+        *token = fPutBack;
+        fHasPutBack = false;
+        return true;
+    }
+
+    if (fEmpty) {
+        return false;
+    }
+
+    return readTokenCore(token);
+}
diff --git a/experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.h b/experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.h
new file mode 100644
index 0000000..6e812c4
--- /dev/null
+++ b/experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.h
@@ -0,0 +1,54 @@
+#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPDFPODOFOTOKENIZER_H_
+#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPDFPODOFOTOKENIZER_H_
+
+#include "stddef.h"
+
+class SkPdfObject;
+class SkPdfMapper;
+class SkPodofoParsedPDF;
+
+namespace PoDoFo {
+class PdfMemDocument;
+class PdfContentsTokenizer;
+}
+
+enum SkPdfTokenType {
+    kKeyword_TokenType,
+    kObject_TokenType,
+    kImageData_TokenType,  // TODO(edisonn): inline images seem to work without it
+};
+
+struct PdfToken {
+    const char*      fKeyword;
+    SkPdfObject*     fObject;
+    SkPdfTokenType   fType;
+
+    PdfToken() : fKeyword(NULL), fObject(NULL) {}
+};
+
+class SkPdfPodofoTokenizer {
+public:
+    SkPdfPodofoTokenizer(const SkPodofoParsedPDF* parser, PoDoFo::PdfContentsTokenizer* tokenizer);
+    SkPdfPodofoTokenizer(const SkPdfObject* objWithStream);
+    SkPdfPodofoTokenizer(const char* buffer, int len);
+
+    virtual ~SkPdfPodofoTokenizer();
+
+    bool readToken(PdfToken* token);
+    bool readTokenCore(PdfToken* token);
+    void PutBack(PdfToken token);
+
+private:
+    const SkPdfMapper* fMapper;
+    const PoDoFo::PdfMemDocument* fDoc;
+    PoDoFo::PdfContentsTokenizer* fTokenizer;
+
+    char* fUncompressedStream;
+    long fUncompressedStreamLength;
+
+    bool fEmpty;
+    bool fHasPutBack;
+    PdfToken fPutBack;
+};
+
+#endif  // EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPDFPODOFOTOKENIZER_H_
diff --git a/experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.cpp b/experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.cpp
new file mode 100644
index 0000000..86d6231
--- /dev/null
+++ b/experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.cpp
@@ -0,0 +1,194 @@
+#include "SkPodofoParsedPDF.h"
+
+#include "SkPdfPodofoTokenizer.h"
+#include "SkPdfHeaders_autogen.h"
+#include "SkPdfMapper_autogen.h"
+#include "SkPdfBasics.h"
+#include "SkPdfParser.h"
+
+#include "podofo.h"
+
+SkPodofoParsedPDF::SkPodofoParsedPDF(const char* path) : fDoc(new PoDoFo::PdfMemDocument(path))
+                                                       , fMapper(new SkPdfMapper(this)) {}
+
+SkPodofoParsedPDF::~SkPodofoParsedPDF() {
+    delete fDoc;
+    delete fMapper;
+}
+
+int SkPodofoParsedPDF::pages() const {
+    return fDoc->GetPageCount();
+}
+
+double SkPodofoParsedPDF::width(int page) const {
+    PoDoFo::PdfRect rect = fDoc->GetPage(page)->GetMediaBox();
+    return rect.GetWidth() + rect.GetLeft();
+}
+
+double SkPodofoParsedPDF::height(int page) const {
+    PoDoFo::PdfRect rect = fDoc->GetPage(page)->GetMediaBox();
+    return rect.GetHeight() + rect.GetBottom();
+}
+
+const SkPdfResourceDictionary* SkPodofoParsedPDF::pageResources(int page) const {
+    SkPdfPageObjectDictionary* pg = NULL;
+    SkPdfObject* obj = make(fDoc->GetPage(page)->GetObject());
+    fMapper->mapPageObjectDictionary(obj, &pg);
+    return pg ? pg->Resources() : NULL;
+}
+
+SkRect SkPodofoParsedPDF::MediaBox(int page) const {
+    PoDoFo::PdfRect rect = fDoc->GetPage(page)->GetMediaBox();
+    SkRect skrect = SkRect::MakeLTRB(SkDoubleToScalar(rect.GetLeft()),
+                                     SkDoubleToScalar(rect.GetBottom()),
+                                     SkDoubleToScalar(rect.GetLeft() + rect.GetWidth()),
+                                     SkDoubleToScalar(rect.GetBottom() + rect.GetHeight()));
+    return skrect;
+}
+
+
+SkPdfPodofoTokenizer* SkPodofoParsedPDF::tokenizerOfPage(int page) const {
+    PoDoFo::PdfContentsTokenizer* t = new PoDoFo::PdfContentsTokenizer(fDoc->GetPage(page));
+    return new SkPdfPodofoTokenizer(this, t);
+}
+
+SkPdfPodofoTokenizer* SkPodofoParsedPDF::tokenizerOfStream(const SkPdfStream* stream) const {
+    if (stream == NULL) {
+        return NULL;
+    }
+
+    char* buffer = NULL;
+    long len = 0;
+    stream->GetFilteredCopy(&buffer, &len);
+    return tokenizerOfBuffer(buffer, len);
+}
+
+SkPdfPodofoTokenizer* SkPodofoParsedPDF::tokenizerOfBuffer(char* buffer, size_t len) const {
+    PoDoFo::PdfContentsTokenizer* t = new PoDoFo::PdfContentsTokenizer(buffer, len);
+    return new SkPdfPodofoTokenizer(this, t);
+}
+
+size_t SkPodofoParsedPDF::objects() const {
+    return fDoc->GetObjects().GetSize();
+}
+
+const SkPdfObject* SkPodofoParsedPDF::object(int i) const {
+    PoDoFo::PdfVecObjects& objects = (PoDoFo::PdfVecObjects&)fDoc->GetObjects();
+    return make(objects[i]);
+}
+
+SkPdfObject* SkPodofoParsedPDF::make(PoDoFo::PdfObject* obj) const {
+    return new SkPdfObject(this, obj);
+}
+
+const SkPdfObject* SkPodofoParsedPDF::make(const PoDoFo::PdfObject* obj) const {
+    return new SkPdfObject(this, obj);
+}
+
+const SkPdfMapper* SkPodofoParsedPDF::mapper() const {
+    return fMapper;
+}
+
+SkPdfNumber* SkPodofoParsedPDF::createNumber(double number) const {
+    return new SkPdfNumber(this, new PoDoFo::PdfObject(PoDoFo::PdfVariant(number)));
+}
+
+SkPdfInteger* SkPodofoParsedPDF::createInteger(int value) const {
+    return new SkPdfInteger(this, new PoDoFo::PdfObject(PoDoFo::PdfVariant((PoDoFo::pdf_int64)value)));
+}
+
+SkPdfString* SkPodofoParsedPDF::createString(char* sz, size_t len) const {
+    // TODO(edisonn): NYI
+    return NULL;
+}
+
+PdfContext* gPdfContext = NULL;
+
+void SkPodofoParsedPDF::drawPage(int page, SkCanvas* canvas) const {
+    SkPdfPodofoTokenizer* tokenizer = tokenizerOfPage(page);
+
+    PdfContext pdfContext(this);
+    pdfContext.fOriginalMatrix = SkMatrix::I();
+    pdfContext.fGraphicsState.fResources = pageResources(page);
+
+    gPdfContext = &pdfContext;
+
+    // TODO(edisonn): get matrix stuff right.
+    // TODO(edisonn): add DPI/scale/zoom.
+    SkScalar z = SkIntToScalar(0);
+    SkRect rect = MediaBox(page);
+    SkScalar w = rect.width();
+    SkScalar h = rect.height();
+
+    SkPoint pdfSpace[4] = {SkPoint::Make(z, z), SkPoint::Make(w, z), SkPoint::Make(w, h), SkPoint::Make(z, h)};
+//                SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoint::Make(w, z), SkPoint::Make(z, z)};
+
+    // TODO(edisonn): add flag for this app to create sourunding buffer zone
+    // TODO(edisonn): add flagg for no clipping.
+    // Use larger image to make sure we do not draw anything outside of page
+    // could be used in tests.
+
+#ifdef PDF_DEBUG_3X
+    SkPoint skiaSpace[4] = {SkPoint::Make(w+z, h+h), SkPoint::Make(w+w, h+h), SkPoint::Make(w+w, h+z), SkPoint::Make(w+z, h+z)};
+#else
+    SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoint::Make(w, z), SkPoint::Make(z, z)};
+#endif
+    //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(w, h)};
+    //SkPoint skiaSpace[2] = {SkPoint::Make(w, z), SkPoint::Make(z, h)};
+
+    //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(z, h)};
+    //SkPoint skiaSpace[2] = {SkPoint::Make(z, h), SkPoint::Make(z, z)};
+
+    //SkPoint pdfSpace[3] = {SkPoint::Make(z, z), SkPoint::Make(z, h), SkPoint::Make(w, h)};
+    //SkPoint skiaSpace[3] = {SkPoint::Make(z, h), SkPoint::Make(z, z), SkPoint::Make(w, 0)};
+
+    SkAssertResult(pdfContext.fOriginalMatrix.setPolyToPoly(pdfSpace, skiaSpace, 4));
+    SkTraceMatrix(pdfContext.fOriginalMatrix, "Original matrix");
+
+
+    pdfContext.fGraphicsState.fMatrix = pdfContext.fOriginalMatrix;
+    pdfContext.fGraphicsState.fMatrixTm = pdfContext.fGraphicsState.fMatrix;
+    pdfContext.fGraphicsState.fMatrixTlm = pdfContext.fGraphicsState.fMatrix;
+
+    canvas->setMatrix(pdfContext.fOriginalMatrix);
+
+#ifndef PDF_DEBUG_NO_PAGE_CLIPING
+    canvas->clipRect(SkRect::MakeXYWH(z, z, w, h), SkRegion::kIntersect_Op, true);
+#endif
+
+// erase with red before?
+//        SkPaint paint;
+//        paint.setColor(SK_ColorRED);
+//        canvas->drawRect(rect, paint);
+
+    PdfMainLooper looper(NULL, tokenizer, &pdfContext, canvas);
+    looper.loop();
+
+    delete tokenizer;
+
+    canvas->flush();
+}
+
+// TODO(edisonn): move in trace util.
+#include "SkMatrix.h"
+#include "SkRect.h"
+
+#ifdef PDF_TRACE
+void SkTraceMatrix(const SkMatrix& matrix, const char* sz) {
+    printf("SkMatrix %s ", sz);
+    for (int i = 0 ; i < 9 ; i++) {
+        printf("%f ", SkScalarToDouble(matrix.get(i)));
+    }
+    printf("\n");
+}
+
+void SkTraceRect(const SkRect& rect, const char* sz) {
+    printf("SkRect %s ", sz);
+    printf("x = %f ", SkScalarToDouble(rect.x()));
+    printf("y = %f ", SkScalarToDouble(rect.y()));
+    printf("w = %f ", SkScalarToDouble(rect.width()));
+    printf("h = %f ", SkScalarToDouble(rect.height()));
+    printf("\n");
+}
+#endif
+
diff --git a/experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.h b/experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.h
new file mode 100644
index 0000000..d694ded
--- /dev/null
+++ b/experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.h
@@ -0,0 +1,59 @@
+#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPODOFOPARSEDPDF_H_
+#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPODOFOPARSEDPDF_H_
+
+#include "SkRect.h"
+
+class SkCanvas;
+
+class SkPdfInteger;
+class SkPdfMapper;
+class SkPdfNumber;
+class SkPdfObject;
+class SkPdfResourceDictionary;
+class SkPdfStream;
+class SkPdfString;
+
+class SkPdfPodofoTokenizer;
+
+namespace PoDoFo {
+class PdfMemDocument;
+class PdfObject;
+}
+
+class SkPodofoParsedPDF {
+public:
+    SkPodofoParsedPDF(const char* path);
+    virtual ~SkPodofoParsedPDF();
+
+    virtual int pages() const;
+    virtual double width(int page) const;
+    virtual double height(int page) const;
+    const SkPdfResourceDictionary* pageResources(int page) const;
+    virtual SkRect MediaBox(int n) const;
+    virtual SkPdfPodofoTokenizer* tokenizerOfPage(int n) const;
+
+    virtual SkPdfPodofoTokenizer* tokenizerOfStream(const SkPdfStream* stream) const;
+    virtual SkPdfPodofoTokenizer* tokenizerOfBuffer(char* buffer, size_t len) const;
+
+    virtual size_t objects() const;
+    virtual const SkPdfObject* object(int i) const;
+
+    PoDoFo::PdfMemDocument* podofo() const {return fDoc;}
+
+    const SkPdfMapper* mapper() const;
+
+    SkPdfNumber* createNumber(double number) const;
+    SkPdfInteger* createInteger(int value) const;
+    SkPdfString* createString(char* sz, size_t len) const;
+
+    void drawPage(int page, SkCanvas* canvas) const;
+
+private:
+    SkPdfObject* make(PoDoFo::PdfObject* obj) const;
+    const SkPdfObject* make(const PoDoFo::PdfObject* obj) const;
+
+    PoDoFo::PdfMemDocument* fDoc;
+    SkPdfMapper* fMapper;
+};
+
+#endif  // EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPODOFOPARSEDPDF_H_
diff --git a/experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.cpp b/experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.cpp
new file mode 100644
index 0000000..1743510
--- /dev/null
+++ b/experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.cpp
@@ -0,0 +1,416 @@
+
+#include "SkPodofoUtils.h"
+#include "SkMatrix.h"
+#include "SkPdfHeaders_autogen.h"
+#include "SkPdfMapper_autogen.h"
+
+#include "podofo.h"
+
+const PoDoFo::PdfObject* resolveReferenceObject(const SkPodofoParsedPDF* pdfDoc,
+                                  const PoDoFo::PdfObject* obj,
+                                  bool resolveOneElementArrays) {
+    while (obj && (obj->IsReference() || (resolveOneElementArrays &&
+                                          obj->IsArray() &&
+                                          obj->GetArray().GetSize() == 1))) {
+        if (obj->IsReference()) {
+            // We need to force the non const, the only update we will do is for recurssion checks.
+            PoDoFo::PdfReference& ref = (PoDoFo::PdfReference&)obj->GetReference();
+            obj = pdfDoc->podofo()->GetObjects().GetObject(ref);
+        } else {
+            obj = &obj->GetArray()[0];
+        }
+    }
+
+    return obj;
+}
+
+// TODO(edisonn): deal with synonyms (/BPC == /BitsPerComponent), here or in GetKey?
+// Always pass long form in key, and have a map of long -> short key
+bool LongFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        long* data) {
+    const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc,
+                                              dict.GetKey(PoDoFo::PdfName(key)));
+
+    if (value == NULL || !value->IsNumber()) {
+        return false;
+    }
+    if (data == NULL) {
+        return true;
+    }
+
+    *data = value->GetNumber();
+    return true;
+}
+
+bool LongFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        long* data) {
+    if (LongFromDictionary(pdfDoc, dict, key, data)) return true;
+    if (abr == NULL || *abr == '\0') return false;
+    return LongFromDictionary(pdfDoc, dict, abr, data);
+}
+
+bool DoubleFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                          const PoDoFo::PdfDictionary& dict,
+                          const char* key,
+                          double* data) {
+    const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc,
+                                              dict.GetKey(PoDoFo::PdfName(key)));
+
+    if (value == NULL || (!value->IsReal() && !value->IsNumber())) {
+        return false;
+    }
+    if (data == NULL) {
+        return true;
+    }
+
+    *data = value->GetReal();
+    return true;
+}
+
+bool DoubleFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                          const PoDoFo::PdfDictionary& dict,
+                          const char* key,
+                          const char* abr,
+                          double* data) {
+    if (DoubleFromDictionary(pdfDoc, dict, key, data)) return true;
+    if (abr == NULL || *abr == '\0') return false;
+    return DoubleFromDictionary(pdfDoc, dict, abr, data);
+}
+
+
+bool BoolFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        bool* data) {
+    const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc,
+                                              dict.GetKey(PoDoFo::PdfName(key)));
+
+    if (value == NULL || !value->IsBool()) {
+        return false;
+    }
+    if (data == NULL) {
+        return true;
+    }
+
+    *data = value->GetBool();
+    return true;
+}
+
+bool BoolFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        bool* data) {
+    if (BoolFromDictionary(pdfDoc, dict, key, data)) return true;
+    if (abr == NULL || *abr == '\0') return false;
+    return BoolFromDictionary(pdfDoc, dict, abr, data);
+}
+
+bool NameFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        std::string* data) {
+    const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc,
+                                              dict.GetKey(PoDoFo::PdfName(key)),
+                                              true);
+    if (value == NULL || !value->IsName()) {
+        return false;
+    }
+    if (data == NULL) {
+        return true;
+    }
+
+    *data = value->GetName().GetName();
+    return true;
+}
+
+bool NameFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        std::string* data) {
+    if (NameFromDictionary(pdfDoc, dict, key, data)) return true;
+    if (abr == NULL || *abr == '\0') return false;
+    return NameFromDictionary(pdfDoc, dict, abr, data);
+}
+
+bool StringFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                          const PoDoFo::PdfDictionary& dict,
+                          const char* key,
+                          std::string* data) {
+    const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc,
+                                              dict.GetKey(PoDoFo::PdfName(key)),
+                                              true);
+    if (value == NULL || (!value->IsString() && !value->IsHexString())) {
+        return false;
+    }
+    if (data == NULL) {
+        return true;
+    }
+
+    *data = value->GetString().GetString();
+    return true;
+}
+
+bool StringFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                          const PoDoFo::PdfDictionary& dict,
+                          const char* key,
+                          const char* abr,
+                          std::string* data) {
+    if (StringFromDictionary(pdfDoc, dict, key, data)) return true;
+    if (abr == NULL || *abr == '\0') return false;
+    return StringFromDictionary(pdfDoc, dict, abr, data);
+}
+
+
+bool SkMatrixFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                            const PoDoFo::PdfDictionary& dict,
+                            const char* key,
+                            SkMatrix** matrix) {
+    const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc,
+                                                    dict.GetKey(PoDoFo::PdfName(key)));
+
+    if (value == NULL || !value->IsArray()) {
+        return false;
+    }
+
+    if (value->GetArray().GetSize() != 6) {
+        return false;
+    }
+
+    double array[6];
+    for (int i = 0; i < 6; i++) {
+        const PoDoFo::PdfObject* elem = resolveReferenceObject(pdfDoc, &value->GetArray()[i]);
+        if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) {
+            return false;
+        }
+        array[i] = elem->GetReal();
+    }
+
+    *matrix = new SkMatrix();
+    **matrix = SkMatrixFromPdfMatrix(array);
+    return true;
+}
+
+bool SkMatrixFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkMatrix** data) {
+    if (SkMatrixFromDictionary(pdfDoc, dict, key, data)) return true;
+    if (abr == NULL || *abr == '\0') return false;
+    return SkMatrixFromDictionary(pdfDoc, dict, abr, data);
+
+}
+
+bool SkRectFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                          const PoDoFo::PdfDictionary& dict,
+                          const char* key,
+                          SkRect** rect) {
+    const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc,
+                                                    dict.GetKey(PoDoFo::PdfName(key)));
+
+    if (value == NULL || !value->IsArray()) {
+        return false;
+    }
+
+    if (value->GetArray().GetSize() != 4) {
+        return false;
+    }
+
+    double array[4];
+    for (int i = 0; i < 4; i++) {
+        const PoDoFo::PdfObject* elem = resolveReferenceObject(pdfDoc, &value->GetArray()[i]);
+        if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) {
+            return false;
+        }
+        array[i] = elem->GetReal();
+    }
+
+    *rect = new SkRect();
+    **rect = SkRect::MakeLTRB(SkDoubleToScalar(array[0]),
+                              SkDoubleToScalar(array[1]),
+                              SkDoubleToScalar(array[2]),
+                              SkDoubleToScalar(array[3]));
+    return true;
+}
+
+bool SkRectFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkRect** data) {
+    if (SkRectFromDictionary(pdfDoc, dict, key, data)) return true;
+    if (abr == NULL || *abr == '\0') return false;
+    return SkRectFromDictionary(pdfDoc, dict, abr, data);
+
+}
+
+
+SkPdfObject* get(const SkPdfObject* obj, const char* key, const char* abr = "") {
+    PoDoFo::PdfObject* podofoObj = NULL;
+    if (obj == NULL) return NULL;
+    const SkPdfDictionary* dict = obj->asDictionary();
+    if (dict == NULL) return NULL;
+    if (!dict->podofo()->IsDictionary()) return NULL;
+    ObjectFromDictionary(dict->doc(), dict->podofo()->GetDictionary(), key, abr, &podofoObj);
+    SkPdfObject* ret = NULL;
+    obj->doc()->mapper()->mapObject(podofoObj, &ret);
+    return ret;
+}
+
+bool ArrayFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                         const PoDoFo::PdfDictionary& dict,
+                         const char* key,
+                         const char* abr,
+                         SkPdfArray* data) {return false;}
+
+bool FileSpecFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                         const PoDoFo::PdfDictionary& dict,
+                         const char* key,
+                         const char* abr,
+                         SkPdfFileSpec* data) {return false;}
+
+bool StreamFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                         const PoDoFo::PdfDictionary& dict,
+                         const char* key,
+                         const char* abr,
+                         SkPdfStream** data);
+
+bool TreeFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                         const PoDoFo::PdfDictionary& dict,
+                         const char* key,
+                         const char* abr,
+                         SkPdfTree** data) {return false;}
+
+bool DateFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                         const PoDoFo::PdfDictionary& dict,
+                         const char* key,
+                         const char* abr,
+                         SkPdfDate* data) {return false;}
+
+bool FunctionFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                         const PoDoFo::PdfDictionary& dict,
+                         const char* key,
+                         const char* abr,
+                         SkPdfFunction* data) {return false;}
+
+
+
+
+bool ArrayFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                              const PoDoFo::PdfDictionary& dict,
+                              const char* key,
+                              SkPdfArray** data) {
+    const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc,
+                                              dict.GetKey(PoDoFo::PdfName(key)),
+                                              true);
+    if (value == NULL || !value->IsArray()) {
+        return false;
+    }
+    if (data == NULL) {
+        return true;
+    }
+
+    return pdfDoc->mapper()->mapArray(value, data);
+}
+
+
+bool ArrayFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkPdfArray** data) {
+    if (ArrayFromDictionary(pdfDoc, dict, key, data)) return true;
+    if (abr == NULL || *abr == '\0') return false;
+    return ArrayFromDictionary(pdfDoc, dict, abr, data);
+}
+
+/*
+bool DictionaryFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                              const PoDoFo::PdfDictionary& dict,
+                              const char* key,
+                              SkPoDoFo::PdfDictionary** data) {
+    const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc,
+                                              dict.GetKey(PoDoFo::PdfName(key)),
+                                              true);
+    if (value == NULL || !value->IsDictionary()) {
+        return false;
+    }
+    if (data == NULL) {
+        return true;
+    }
+
+    return pdfDoc->mapper()->mapDictionary(value, data);
+}
+
+bool DictionaryFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkPoDoFo::PdfDictionary** data) {
+    if (DictionaryFromDictionary(pdfDoc, dict, key, data)) return true;
+    if (abr == NULL || *abr == '\0') return false;
+    return DictionaryFromDictionary(pdfDoc, dict, abr, data);
+}
+*/
+
+bool ObjectFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                          const PoDoFo::PdfDictionary& dict,
+                          const char* key,
+                          PoDoFo::PdfObject** data) {
+    const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc,
+                                              dict.GetKey(PoDoFo::PdfName(key)),
+                                              true);
+    if (value == NULL) {
+        return false;
+    }
+    if (data == NULL) {
+        return true;
+    }
+    *data = (PoDoFo::PdfObject*)value;
+    return true;
+}
+
+bool ObjectFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        PoDoFo::PdfObject** data) {
+    if (ObjectFromDictionary(pdfDoc, dict, key, data)) return true;
+    if (abr == NULL || *abr == '\0') return false;
+    return ObjectFromDictionary(pdfDoc, dict, abr, data);
+}
+
+bool StreamFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                          const PoDoFo::PdfDictionary& dict,
+                          const char* key,
+                          SkPdfStream** data) {
+    const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc,
+                                              dict.GetKey(PoDoFo::PdfName(key)),
+                                              true);
+    if (value == NULL) {
+        return false;
+    }
+    if (data == NULL) {
+        return true;
+    }
+    return pdfDoc->mapper()->mapStream(value, data);
+}
+
+bool StreamFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkPdfStream** data) {
+    if (StreamFromDictionary(pdfDoc, dict, key, data)) return true;
+    if (abr == NULL || *abr == '\0') return false;
+    return StreamFromDictionary(pdfDoc, dict, abr, data);
+}
+
+
diff --git a/experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.h b/experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.h
new file mode 100644
index 0000000..b180f80
--- /dev/null
+++ b/experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.h
@@ -0,0 +1,122 @@
+#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPODOFOUTILS_H_
+#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPODOFOUTILS_H_
+
+#include <string>
+#include "SkPdfNYI.h"
+
+class SkMatrix;
+class SkRect;
+
+namespace PoDoFo {
+class PdfDictionary;
+class PdfObject;
+}
+
+class SkPodofoParsedPDF;
+
+const PoDoFo::PdfObject* resolveReferenceObject(const SkPodofoParsedPDF* pdfDoc,
+                                  const PoDoFo::PdfObject* obj,
+                                  bool resolveOneElementArrays = false);
+
+bool LongFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        long* data);
+
+bool DoubleFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                          const PoDoFo::PdfDictionary& dict,
+                          const char* key,
+                          const char* abr,
+                          double* data);
+
+bool BoolFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        bool* data);
+
+bool NameFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        std::string* data);
+
+bool StringFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                          const PoDoFo::PdfDictionary& dict,
+                          const char* key,
+                          const char* abr,
+                          std::string* data);
+/*
+class SkPoDoFo::PdfDictionary;
+bool DictionaryFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                              const PoDoFo::PdfDictionary& dict,
+                              const char* key,
+                              const char* abr,
+                              SkPoDoFo::PdfDictionary** data);
+*/
+
+bool skpdfmap(const SkPodofoParsedPDF& podofoDoc, const PoDoFo::PdfObject& podofoObj, PoDoFo::PdfObject** out);
+
+bool ObjectFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        PoDoFo::PdfObject** data);
+
+
+class SkPdfArray;
+class SkPdfStream;
+
+bool ArrayFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkPdfArray** data);
+
+bool SkMatrixFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkMatrix** data);
+
+bool FileSpecFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkPdfFileSpec* data);
+
+
+bool StreamFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkPdfStream** data);
+
+bool TreeFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkPdfTree** data);
+
+bool DateFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkPdfDate* data);
+
+bool SkRectFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkRect** data);
+
+bool FunctionFromDictionary(const SkPodofoParsedPDF* pdfDoc,
+                        const PoDoFo::PdfDictionary& dict,
+                        const char* key,
+                        const char* abr,
+                        SkPdfFunction* data);
+
+SkMatrix SkMatrixFromPdfMatrix(double array[6]);
+
+#endif  // EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPODOFOUTILS_H_
diff --git a/experimental/PdfViewer/spec2def.py b/experimental/PdfViewer/spec2def.py
index b53e251..8b77e72 100644
--- a/experimental/PdfViewer/spec2def.py
+++ b/experimental/PdfViewer/spec2def.py
@@ -292,7 +292,7 @@
   
   return ret
   
-def commitRow():
+def commitRow(fspecPy):
   global columnValues
   global emitedDitionaryName
   global table
@@ -393,27 +393,27 @@
     comment = fix(tableToClassName[tableKey][1])
     
     if len(tableToClassName[tableKey]) >= 3 and tableToClassName[tableKey][2] != '':
-      print('  pdfspec.addClass(\'' + emitedDitionaryName + '\', \'' + tableToClassName[tableKey][2] + '\', \'' + comment + '\')\\')
+      fspecPy.write('  pdfspec.addClass(\'' + emitedDitionaryName + '\', \'' + tableToClassName[tableKey][2] + '\', \'' + comment + '\')\\\n')
     else:
-      print('  pdfspec.addClass(\'' + emitedDitionaryName + '\', \'Dictionary\', \'' + comment + '\')\\')
+      fspecPy.write('  pdfspec.addClass(\'' + emitedDitionaryName + '\', \'Dictionary\', \'' + comment + '\')\\\n')
 
   if len(tableToClassName[tableKey]) >= 4 and columnValues[0] in tableToClassName[tableKey][3]:
     required = True
 
   if required:
-    print('      .required(\'NULL\')\\')
+    fspecPy.write('      .required(\'NULL\')\\\n')
   else:
-    print('      .optional()\\')
+    fspecPy.write('      .optional()\\\n')
     
-  print('          .field(\'' + columnValues[0] + '\')\\')
-  print('          .name(\'' + columnValues[0] + '\')\\')
-  print('          .type(\'' + columnValues[1] + '\')\\')
-  print('          .comment(\'' + columnValues[2] + '\')\\')
+  fspecPy.write('          .field(\'' + columnValues[0] + '\')\\\n')
+  fspecPy.write('          .name(\'' + columnValues[0] + '\')\\\n')
+  fspecPy.write('          .type(\'' + columnValues[1] + '\')\\\n')
+  fspecPy.write('          .comment(\'' + columnValues[2] + '\')\\\n')
 
   if len(tableToClassName[tableKey]) >= 4 and columnValues[0] in tableToClassName[tableKey][3]:
-    print('          .must(' + tableToClassName[tableKey][3][columnValues[0]] + ')\\')
+    fspecPy.write('          .must(' + tableToClassName[tableKey][3][columnValues[0]] + ')\\\n')
 
-  print('          .done().done()\\')
+  fspecPy.write('          .done().done()\\\n')
   
   
   columnValues = None
@@ -429,7 +429,7 @@
   if third.rstrip() != '':
     columnValues[2] = columnValues[2] + '\n' + third.rstrip()
 
-def rebaseTable(line):
+def rebaseTable(fspecPy, line):
   global knownTypes
   global columnWidth
   
@@ -445,7 +445,7 @@
     i = i + 1
     
   if words[i].startswith('(Optional') or words[i].startswith('(Required'):
-    commitRow()
+    commitRow(fspecPy)
     
     columnWidth[0] = line.find(words[1])
     
@@ -458,24 +458,24 @@
   return False
     
     
-def stopTable():
+def stopTable(fspecPy):
   global tableHeaderFound
   global emitedDitionaryName
 
   if not inTable():
     return
   
-  commitRow()
+  commitRow(fspecPy)
   tableHeaderFound = False
   emitedDitionaryName = ''
-  print('      .done()')
-  print
+  fspecPy.write('      .done()\n')
+  fspecPy.write('\n')
     
 
 def killTable():
   return
 
-def processLineCore(line):
+def processLineCore(fspecPy, line):
   global lines
   global tableLine
   global tableRow
@@ -483,7 +483,7 @@
   global columnValues
   global mustFollowTableHeader
   
-  global fnewspec
+  #global fnewspec
   
   lines = lines + 1
   
@@ -493,12 +493,12 @@
   
   words = line.split()
   if len(words) == 0:
-    stopTable()
+    stopTable(fspecPy)
     return False
         
   isTableHeader = re.search('^[\s]*(TABLE [0-9].[0-9][0-9]?)', striped)
   if isTableHeader:
-    stopTable()
+    stopTable(fspecPy)
     tableDescriptionFound(striped)
     mustFollowTableHeader = True
     return False
@@ -535,7 +535,7 @@
       newRow(first, second, third)
       return True
     
-    if rebaseTable(striped):
+    if rebaseTable(fspecPy, striped):
       first = striped[0 : columnWidth[0]]
       second = striped[columnWidth[0] : columnWidth[0] + columnWidth[1]]
       third = striped[columnWidth[0] + columnWidth[1] :]
@@ -549,15 +549,15 @@
       return True
       
     if len(first.split()) > 1:
-      stopTable()
+      stopTable(fspecPy)
       return False
 
     if first != '' and first[0] == ' ':
-      stopTable()
+      stopTable(fspecPy)
       return False
 
     if first != '' and second != '' and third == '':
-      stopTable()
+      stopTable(fspecPy)
       return False
 
     if first == '' and second != '' and second[0] != ' ':
@@ -565,7 +565,7 @@
         appendRow(second, third)
         return True
       else:
-        stopTable()
+        stopTable(fspecPy)
         return False
 
     if first != '' and second != '' and third[0] != '(':
@@ -573,61 +573,65 @@
       return False
       
     if first == '' and second != '' and second[0] == ' ':
-      stopTable()
+      stopTable(fspecPy)
       return False
 
     if first != '' and second != '' and third[0] == '(':
-      commitRow()
+      commitRow(fspecPy)
       newRow(first, second, third)
       return True
     
     return False
   return False
   
-def processLine(line):
-  global fnewspec
+def processLine(fspecPy, line):
+  #global fnewspec
   
-  inSpec = processLineCore(line)
+  inSpec = processLineCore(fspecPy, line)
   
   #just return, use the next lines if you wish to rewrite spec
-  #return
+  return
   
   if inSpec:
     #resize colum with types
     line = line[:columnWidth[0] + columnWidth[1]] + (' ' * (60 - columnWidth[1])) + line[columnWidth[0] + columnWidth[1]:]
     line = line[:columnWidth[0]] + (' ' * (40 - columnWidth[0])) + line[columnWidth[0]:]
   
-  fnewspec.write(line)
+  #fnewspec.write(line)
   
 
 def generateDef():
   global lines
-  global fnewspec
+  #global fnewspec
   
-  fnewspec = open('PdfReference-okular-2.txt', 'w')
+  #fnewspec = open('PdfReference-okular-2.txt', 'w')
   
-  print 'import datatypes'
-  print
+  # pdf spec in text format
+  fspecText = open(sys.argv[1], 'r')
+  
+  # pdf spec in python directives 
+  fspecPy = open(sys.argv[2], 'w')
+  
+  fspecPy.write('import datatypes\n')
+  fspecPy.write('\n')
 
-  print 'def buildPdfSpec(pdfspec):'
+  fspecPy.write('def buildPdfSpec(pdfspec):\n')
   
-  for line in sys.stdin:
-    processLine(line)
+  for line in fspecText:
+    processLine(fspecPy, line)
    
   # close last table if it was not closed already 
-  stopTable()
+  stopTable(fspecPy)
   
-  print
+  fspecPy.write('\n')
 
-  print 'def addDictionaryTypesTo(knowTypes):'  
+  fspecPy.write('def addDictionaryTypesTo(knowTypes):\n')  
   for e in tableToClassName:
-    print('  knowTypes[\'' + tableToClassName[e][0] + '\'] = [\'SkPdf' + tableToClassName[e][0] + '*\', \'' + tableToClassName[e][0] + 'FromDictionary\', datatypes.CppNull(), \'ret->podofo()->GetDataType() == ePdfDataType_Dictionary\']')
-  print
-  print
-
+    fspecPy.write('  knowTypes[\'' + tableToClassName[e][0] + '\'] = [\'SkPdf' + tableToClassName[e][0] + '*\', \'SkPdf' + tableToClassName[e][0] + 'FromDictionary\', datatypes.CppNull(), \'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Dictionary\', \'A_DICTIONARY\']\n')
+  fspecPy.write('\n')
   
   #print lines
-  fnewspec.close()
+  #fnewspec.close()
 
 if '__main__' == __name__:
   sys.exit(generateDef())
\ No newline at end of file
diff --git a/gyp/pdfviewer.gyp b/gyp/pdfviewer.gyp
index 3f78a48..55e6b1b 100644
--- a/gyp/pdfviewer.gyp
+++ b/gyp/pdfviewer.gyp
@@ -23,8 +23,45 @@
         '../experimental/PdfViewer/SkPdfFont.cpp',
         '../experimental/PdfViewer/SkPdfParser.cpp',
         '../experimental/PdfViewer/SkPdfUtils.cpp',
-        '../experimental/PdfViewer/pdfparser/podofo/autogen/SkPdfPodofoMapper_autogen.cpp',
+        #'../experimental/PdfViewer/SkPdfNYI.cpp',
+        #podofo
+        '../experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.cpp',
+        '../experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.cpp',
+        '../experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.cpp',
+        '../experimental/PdfViewer/pdfparser/podofo/autogen/SkPdfMapper_autogen.cpp',
         '../experimental/PdfViewer/pdfparser/podofo/autogen/SkPdfHeaders_autogen.cpp',
+        #native TODO
+
+        # libraries.cc is generated by the js2c action below.
+        #'<(INTERMEDIATE_DIR)/libraries.cc',
+      ],
+      'actions': [
+        {
+          'action_name': 'spec2def',
+          'inputs': [
+            '../experimental/PdfViewer/spec2def.py',
+            '../experimental/PdfViewer/PdfReference-okular-1.txt',
+          ],
+          'outputs': [
+            '../experimental/PdfViewer/autogen/pdfspec_autogen.py',
+          ],
+          'action': ['python', '../experimental/PdfViewer/spec2def.py', '../experimental/PdfViewer/PdfReference-okular-1.txt', '../experimental/PdfViewer/autogen/pdfspec_autogen.py'],
+        },
+        {
+          'action_name': 'generate_code',
+          'inputs': [
+            '../experimental/PdfViewer/generate_code.py',
+            '../experimental/PdfViewer/autogen/pdfspec_autogen.py',
+          ],
+          'outputs': [
+            '../experimental/PdfViewer/pdfparser/autogen/SkPdfEnums_autogen.h',
+            '../experimental/PdfViewer/pdfparser/podofo/autogen/SkPdfMapper_autogen.cpp',
+            '../experimental/PdfViewer/pdfparser/podofo/autogen/SkPdfHeaders_autogen.cpp',
+            # TODO(edisonn): ok, there are many more files here, which we should list but since
+            # any change in the above should trigger a change here, we should be fine normally
+          ],
+          'action': ['python', '../experimental/PdfViewer/generate_code.py', '../experimental/PdfViewer/pdfparser/'],
+        },
       ],
       'include_dirs': [
         '../third_party/externals/podofo/src/base',
@@ -33,10 +70,9 @@
         '../tools',
         '../experimental/PdfViewer',
         '../experimental/PdfViewer/pdfparser',
+        '../experimental/PdfViewer/pdfparser/autogen',
         '../experimental/PdfViewer/pdfparser/podofo',
         '../experimental/PdfViewer/pdfparser/podofo/autogen',
-        #'../experimental/PdfViewer/pdfparser/native',
-        #'../experimental/PdfViewer/pdfparser/native/autogen',
       ],
       'dependencies': [
         'core.gyp:core',
@@ -66,12 +102,12 @@
         '../experimental/PdfViewer/pdf_viewer_main.cpp',
       ],
       'include_dirs': [
-        '../third_party/externals/podofo/src/base',
-        '../third_party/externals/podofo/src',
-        '../third_party/externals/podofo',
         '../tools',
         '../experimental/PdfViewer',
-        '../experimental/PdfViewer/autogen',
+        '../experimental/PdfViewer/pdfparser',
+        '../experimental/PdfViewer/pdfparser/autogen',
+        '../experimental/PdfViewer/pdfparser/podofo',
+        '../experimental/PdfViewer/pdfparser/podofo/autogen',
       ],
       'dependencies': [
         'core.gyp:core',