[PDF] Make stream compression optional on a per device basis.

There are a lot of small pieces to make this change work:
- SkPDFDocument (and SkPDFCatalog) take flags to disable compression (and font embedding - not implemented yet, can disable font subsetting for now).
- SkPDFStream now defers compression until the size/emit step.
- Classes that *had* a stream (because they didn't know the stream size at construction time) now *are* streams to make the substitution work correctly.
- The SkPDFShader implementation got pulled apart into two classes, one that is a SkPDFDict, and one that is a SkPDFStream (making the common ancestor SkPDFObject).
- Added helper methods in SkPDFObject for children that have simple resource lists.
- Added an iterator to SkPDFDict so that a substitute SkPDFStream can get a copy of the stream dictionary.
- Change SkPDFDocument to have a pointer to an SkPDFCatalog to remove a new circular header reference.

Review URL: http://codereview.appspot.com/4700045

git-svn-id: http://skia.googlecode.com/svn/trunk@1911 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/pdf/SkPDFTypes.cpp b/src/pdf/SkPDFTypes.cpp
index 810d860..a026d69 100644
--- a/src/pdf/SkPDFTypes.cpp
+++ b/src/pdf/SkPDFTypes.cpp
@@ -48,14 +48,32 @@
     stream->writeText("\nendobj\n");
 }
 
-SkPDFObjRef::SkPDFObjRef(SkPDFObject* obj) : fObj(obj) {}
-SkPDFObjRef::~SkPDFObjRef() {}
-
 size_t SkPDFObject::getIndirectOutputSize(SkPDFCatalog* catalog) {
     return catalog->getObjectNumberSize(this) + strlen(" obj\n") +
         this->getOutputSize(catalog, false) + strlen("\nendobj\n");
 }
 
+void SkPDFObject::AddResourceHelper(SkPDFObject* resource,
+                                    SkTDArray<SkPDFObject*>* list) {
+    list->push(resource);
+    resource->ref();
+}
+
+void SkPDFObject::GetResourcesHelper(SkTDArray<SkPDFObject*>* resources,
+                                     SkTDArray<SkPDFObject*>* result) {
+    if (resources->count()) {
+        result->setReserve(result->count() + resources->count());
+        for (int i = 0; i < resources->count(); i++) {
+            result->push((*resources)[i]);
+            (*resources)[i]->ref();
+            (*resources)[i]->getResources(result);
+        }
+    }
+}
+
+SkPDFObjRef::SkPDFObjRef(SkPDFObject* obj) : fObj(obj) {}
+SkPDFObjRef::~SkPDFObjRef() {}
+
 void SkPDFObjRef::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
                              bool indirect) {
     SkASSERT(!indirect);
@@ -258,6 +276,10 @@
 SkPDFName::SkPDFName(const SkString& name) : fValue(FormatName(name)) {}
 SkPDFName::~SkPDFName() {}
 
+bool SkPDFName::operator==(const SkPDFName& b) const {
+    return fValue == b.fValue;
+}
+
 void SkPDFName::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
                            bool indirect) {
     SkASSERT(!indirect);
@@ -433,3 +455,19 @@
     }
     fValue.reset();
 }
+
+SkPDFDict::Iter::Iter(const SkPDFDict& dict)
+    : fIter(dict.fValue.begin()),
+      fStop(dict.fValue.end()) {
+}
+
+SkPDFName* SkPDFDict::Iter::next(SkPDFObject** value) {
+    if (fIter != fStop) {
+        Rec* cur = fIter;
+        fIter++;
+        *value = cur->value;
+        return cur->key;
+    }
+    *value = NULL;
+    return NULL;
+}