pdfviewer: add indexed rbg image support, enhanche caching(setData) for SkPdfObject

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

git-svn-id: http://skia.googlecode.com/svn/trunk@10534 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp
index 306bf07..6386f98 100644
--- a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp
@@ -306,7 +306,7 @@
     }
 
     if (storeCatalog) {
-        const SkPdfObject* ref = trailer->Root(NULL);
+        SkPdfObject* ref = trailer->Root(NULL);
         if (ref == NULL || !ref->isReference()) {
             // TODO(edisonn): oops, we have to fix the corrup pdf file
             return current;
@@ -384,7 +384,7 @@
 }
 
 void SkNativeParsedPDF::fillPages(SkPdfPageTreeNodeDictionary* tree) {
-    const SkPdfArray* kids = tree->Kids(this);
+    SkPdfArray* kids = tree->Kids(this);
     if (kids == NULL) {
         *fPages.append() = (SkPdfPageObjectDictionary*)tree;
         return;
@@ -392,7 +392,7 @@
 
     int cnt = kids->size();
     for (int i = 0; i < cnt; i++) {
-        const SkPdfObject* obj = resolveReference(kids->objAtAIndex(i));
+        SkPdfObject* obj = resolveReference(kids->objAtAIndex(i));
         if (fMapper->mapPageObjectDictionary(obj) != kPageObjectDictionary_SkPdfObjectType) {
             *fPages.append() = (SkPdfPageObjectDictionary*)obj;
         } else {
@@ -506,7 +506,7 @@
 
 // TODO(edisonn): fix infinite loop if ref to itself!
 // TODO(edisonn): perf, fix refs at load, and resolve will simply return fResolvedReference?
-SkPdfObject* SkNativeParsedPDF::resolveReference(const SkPdfObject* ref) {
+SkPdfObject* SkNativeParsedPDF::resolveReference(SkPdfObject* ref) {
     if (ref && ref->isReference()) {
         int id = ref->referenceId();
         // TODO(edisonn): generation/updates not supported now
diff --git a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h
index d073f00..de71bf6 100644
--- a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h
+++ b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h
@@ -64,7 +64,7 @@
     // the string does not own the char*
     SkPdfString* createString(const unsigned char* sz, size_t len) const;
 
-    SkPdfObject* resolveReference(const SkPdfObject* ref);
+    SkPdfObject* resolveReference(SkPdfObject* ref);
 
     // Reports an approximation of all the memory usage.
     size_t bytesUsed() const;
@@ -95,7 +95,7 @@
     SkPdfMapper* fMapper;
     const unsigned char* fFileContent;
     size_t fContentLength;
-    const SkPdfObject* fRootCatalogRef;
+    SkPdfObject* fRootCatalogRef;
     SkPdfCatalogDictionary* fRootCatalog;
 
     mutable SkTDArray<PublicObjectEntry> fObjects;
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
index 8dd5d30..637eb4d 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp
@@ -32,9 +32,11 @@
 static void TRACE_INDENT(int level, const char* type) {
     static int id = 0;
     id++;
+#if 0
     if (478613 == id) {
         printf("break;\n");
     }
+#endif
     // all types should have 2 letters, so the text is alligned nicely
     printf("\n%10i %15s: ", id, type);
     for (int i = 0 ; i < level; i++) {
@@ -158,7 +160,6 @@
         }
         array->appendInArray(newObj);
     }
-    printf("break;\n");  // DO NOT SUBMIT!
     // TODO(edisonn): report not reached, we should never get here
     // TODO(edisonn): there might be a bug here, enable an assert and run it on files
     // or it might be that the files were actually corrupted
@@ -954,9 +955,11 @@
 #ifdef PDF_TRACE_READ_TOKEN
     static int read_op = 0;
     read_op++;
+#if 0
     if (548 == read_op) {
         printf("break;\n");
     }
+#endif
     printf("%i READ %s %s\n", read_op, token->fType == kKeyword_TokenType ? "Keyword" : "Object", token->fKeyword ? std::string(token->fKeyword, token->fKeywordLength).c_str() : token->fObject->toString().c_str());
 #endif
 
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfObject.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfObject.cpp
index eb342af..a02d789 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfObject.cpp
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfObject.cpp
@@ -6,6 +6,9 @@
 #include "SkStream.h"
 #include "SkPdfNativeTokenizer.h"
 
+#include "SkBitmap.h"
+#include "SkPdfFont.h"
+
 SkPdfObject SkPdfObject::kNull = SkPdfObject::makeNull();
 
 bool SkPdfObject::applyFlateDecodeFilter() {
@@ -86,3 +89,21 @@
 
     return true;
 }
+
+void SkPdfObject::releaseData() {
+    if (fData) {
+        switch (fDataType) {
+            case kFont_Data:
+                delete (SkPdfFont*)fData;
+                break;
+            case kBitmap_Data:
+                delete (SkBitmap*)fData;
+                break;
+            default:
+                SkASSERT(false);
+                break;
+        }
+    }
+    fData = NULL;
+    fDataType = kEmpty_Data;
+}
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfObject.h b/experimental/PdfViewer/pdfparser/native/SkPdfObject.h
index 29780d0..1fb4e1f 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfObject.h
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfObject.h
@@ -49,6 +49,12 @@
          kUndefined_PdfObjectType,  // per 1.4 spec, if the same key appear twice in the dictionary, the value is undefined
      };
 
+     enum DataType {
+         kEmpty_Data,
+         kFont_Data,
+         kBitmap_Data,
+     };
+
 private:
     struct Reference {
         unsigned int fId;
@@ -76,21 +82,33 @@
         Reference fRef;
     };
     SkTDict<SkPdfObject*>* fMap;
+
+    // TODO(edisonn): rename data with cache
     void* fData;
+    DataType fDataType;
 
 
 public:
 
-    SkPdfObject() : fObjectType(kInvalid_PdfObjectType), fMap(NULL), fData(NULL) {}
+    SkPdfObject() : fObjectType(kInvalid_PdfObjectType), fMap(NULL), fData(NULL), fDataType(kEmpty_Data) {}
 
-    inline void* data() {
-        return fData;
+
+    inline bool hasData(DataType type) {
+        return type == fDataType;
     }
 
-    inline void setData(void* data) {
+    inline void* data(DataType type) {
+        return type == fDataType ? fData : NULL;
+    }
+
+    inline void setData(void* data, DataType type) {
+        releaseData();
+        fDataType = type;
         fData = data;
     }
 
+    void releaseData();
+
 //    ~SkPdfObject() {
 //        //reset();  must be called manually!
 //    }
@@ -114,6 +132,7 @@
                 break;
         }
         fObjectType = kInvalid_PdfObjectType;
+        releaseData();
     }
 
     ObjectType type() { return fObjectType; }
@@ -604,6 +623,10 @@
         return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
     }
 
+    bool isHexString() const {
+        return fObjectType == kHexString_PdfObjectType;
+    }
+
     bool isMatrix() const {
         return fObjectType == kArray_PdfObjectType && fArray->count() == 6; // NYI + and elems are numbers
     }
@@ -867,7 +890,9 @@
 
             case kHexString_PdfObjectType:
                 str.append("<");
-                str.append((const char*)fStr.fBuffer, fStr.fBytes);
+                for (unsigned int i = 0 ; i < fStr.fBytes; i++) {
+                    str.appendf("%02x", (unsigned int)fStr.fBuffer[i]);
+                }
                 str.append(">");
                 break;
 
@@ -908,9 +933,9 @@
                         const unsigned char* stream = NULL;
                         size_t length = 0;
                         if (GetFilteredStreamRef(&stream, &length)) {
-                            str.append("stream");
+                            str.append("stream\n");
                             str.append((const char*)stream, length > 256 ? 256 : length);
-                            str.append("endstream");
+                            str.append("\nendstream");
                         } else {
                             str.append("stream STREAM_ERROR endstream");
                         }