SkPDF: Factor SkPDFCatalog into SkPDFObjNumMap and SkPDFSubstituteMap

Motivation: Keep separate features separate.  Also, future
linearization work will need to have several objNumMap
objects share a substituteMap.  Also "catalog" has a
specific meaning in PDF.  This catalog did not map to that
catalog.

-   Modify SkPDFObject::emitObject and SkPDFObject::addResources
    interface to requiore SkPDFObjNumMap and SkPDFSubstituteMap.
-   SkPDFObjNumMap const in SkPDFObject::emitObject.
-   Remove SkPDFCatalog.cpp/.h
-   Modify SkDocument_PDF.cpp to use new functions
-   Fold in SkPDFStream::populate
-   Fold in SkPDFBitmap::emitDict
-   Move SkPDFObjNumMap and SkPDFSubstituteMap to SkPDFTypes.h
-   Note (via assert) that SkPDFArray & SkPDFDict don't need to
    check substitutes.
-   Remove extra space from SkPDFDict serialization.
-   SkPDFBitmap SkPDFType0Font SkPDFGraphicState SkPDFStream
    updated to new interface.
-   PDFPrimitivesTest updated for new interface.

BUG=skia:3585

Review URL: https://codereview.chromium.org/1049753002
diff --git a/src/pdf/SkPDFTypes.cpp b/src/pdf/SkPDFTypes.cpp
index 02c5573..e80d118 100644
--- a/src/pdf/SkPDFTypes.cpp
+++ b/src/pdf/SkPDFTypes.cpp
@@ -7,7 +7,6 @@
  */
 
 
-#include "SkPDFCatalog.h"
 #include "SkPDFTypes.h"
 #include "SkStream.h"
 
@@ -25,17 +24,20 @@
 
 SkPDFObjRef::~SkPDFObjRef() {}
 
-void SkPDFObjRef::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
-    SkPDFObject* obj = catalog->getSubstituteObject(fObj);
-    stream->writeDecAsText(catalog->getObjectNumber(obj));
+void SkPDFObjRef::emitObject(SkWStream* stream,
+                             const SkPDFObjNumMap& objNumMap,
+                             const SkPDFSubstituteMap& substitutes) {
+    SkPDFObject* obj = substitutes.getSubstitute(fObj);
+    stream->writeDecAsText(objNumMap.getObjectNumber(obj));
     stream->writeText(" 0 R");  // Generation number is always 0.
 }
 
-void SkPDFObjRef::addResources(SkPDFCatalog* catalog) const {
-    SkPDFObject* obj = catalog->getSubstituteObject(fObj);
+void SkPDFObjRef::addResources(SkPDFObjNumMap* catalog,
+                               const SkPDFSubstituteMap& substitutes) const {
+    SkPDFObject* obj = substitutes.getSubstitute(fObj);
     SkASSERT(obj);
     if (catalog->addObject(obj)) {
-        obj->addResources(catalog);
+        obj->addResources(catalog, substitutes);
     }
 }
 
@@ -44,7 +46,9 @@
 SkPDFInt::SkPDFInt(int32_t value) : fValue(value) {}
 SkPDFInt::~SkPDFInt() {}
 
-void SkPDFInt::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
+void SkPDFInt::emitObject(SkWStream* stream,
+                          const SkPDFObjNumMap&,
+                          const SkPDFSubstituteMap&) {
     stream->writeDecAsText(fValue);
 }
 
@@ -53,12 +57,10 @@
 SkPDFBool::SkPDFBool(bool value) : fValue(value) {}
 SkPDFBool::~SkPDFBool() {}
 
-void SkPDFBool::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
-    if (fValue) {
-        stream->writeText("true");
-    } else {
-        stream->writeText("false");
-    }
+void SkPDFBool::emitObject(SkWStream* stream,
+                          const SkPDFObjNumMap&,
+                          const SkPDFSubstituteMap&) {
+    stream->writeText(fValue ? "true" : "false");
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -66,8 +68,10 @@
 SkPDFScalar::SkPDFScalar(SkScalar value) : fValue(value) {}
 SkPDFScalar::~SkPDFScalar() {}
 
-void SkPDFScalar::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
-    Append(fValue, stream);
+void SkPDFScalar::emitObject(SkWStream* stream,
+                             const SkPDFObjNumMap&,
+                             const SkPDFSubstituteMap&) {
+    SkPDFScalar::Append(fValue, stream);
 }
 
 // static
@@ -135,7 +139,9 @@
 
 SkPDFString::~SkPDFString() {}
 
-void SkPDFString::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
+void SkPDFString::emitObject(SkWStream* stream,
+                             const SkPDFObjNumMap&,
+                             const SkPDFSubstituteMap&) {
     stream->write(fValue.c_str(), fValue.size());
 }
 
@@ -214,7 +220,9 @@
     return fValue == b.fValue;
 }
 
-void SkPDFName::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
+void SkPDFName::emitObject(SkWStream* stream,
+                             const SkPDFObjNumMap&,
+                             const SkPDFSubstituteMap&) {
     stream->write(fValue.c_str(), fValue.size());
 }
 
@@ -245,10 +253,13 @@
     fValue.unrefAll();
 }
 
-void SkPDFArray::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
+void SkPDFArray::emitObject(SkWStream* stream,
+                             const SkPDFObjNumMap& objNumMap,
+                             const SkPDFSubstituteMap& substitutes) {
     stream->writeText("[");
     for (int i = 0; i < fValue.count(); i++) {
-        catalog->getSubstituteObject(fValue[i])->emitObject(stream, catalog);
+        SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]);
+        fValue[i]->emitObject(stream, objNumMap, substitutes);
         if (i + 1 < fValue.count()) {
             stream->writeText(" ");
         }
@@ -256,9 +267,11 @@
     stream->writeText("]");
 }
 
-void SkPDFArray::addResources(SkPDFCatalog* catalog) const {
+void SkPDFArray::addResources(SkPDFObjNumMap* catalog,
+                              const SkPDFSubstituteMap& substitutes) const {
     for (int i = 0; i < fValue.count(); i++) {
-        catalog->getSubstituteObject(fValue[i])->addResources(catalog);
+        SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]);
+        fValue[i]->addResources(catalog, substitutes);
     }
 }
 
@@ -313,26 +326,33 @@
     return fValue.count();
 }
 
-void SkPDFDict::emitObject(SkWStream* stream, SkPDFCatalog* catalog) {
+void SkPDFDict::emitObject(SkWStream* stream,
+                           const SkPDFObjNumMap& objNumMap,
+                           const SkPDFSubstituteMap& substitutes) {
     stream->writeText("<<");
     for (int i = 0; i < fValue.count(); i++) {
         SkASSERT(fValue[i].key);
         SkASSERT(fValue[i].value);
-        fValue[i].key->emitObject(stream, catalog);
+        SkASSERT(substitutes.getSubstitute(fValue[i].key) == fValue[i].key);
+        SkASSERT(substitutes.getSubstitute(fValue[i].value) == fValue[i].value);
+        fValue[i].key->emitObject(stream, objNumMap, substitutes);
         stream->writeText(" ");
-        catalog->getSubstituteObject(fValue[i].value)
-                ->emitObject(stream, catalog);
-        stream->writeText("\n");
+        fValue[i].value->emitObject(stream, objNumMap, substitutes);
+        if (i + 1 < fValue.count()) {
+            stream->writeText("\n");
+        }
     }
     stream->writeText(">>");
 }
 
-void SkPDFDict::addResources(SkPDFCatalog* catalog) const {
+void SkPDFDict::addResources(SkPDFObjNumMap* catalog,
+                             const SkPDFSubstituteMap& substitutes) const {
     for (int i = 0; i < fValue.count(); i++) {
         SkASSERT(fValue[i].key);
         SkASSERT(fValue[i].value);
-        fValue[i].key->addResources(catalog);
-        catalog->getSubstituteObject(fValue[i].value)->addResources(catalog);
+        fValue[i].key->addResources(catalog, substitutes);
+        SkASSERT(substitutes.getSubstitute(fValue[i].value) == fValue[i].value);
+        fValue[i].value->addResources(catalog, substitutes);
     }
 }
 
@@ -394,3 +414,40 @@
                 Rec(SkRef(other.fValue[i].key), SkRef(other.fValue[i].value));
     }
 }
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkPDFSubstituteMap::~SkPDFSubstituteMap() {
+    fSubstituteMap.foreach(
+            [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); });
+}
+
+void SkPDFSubstituteMap::setSubstitute(SkPDFObject* original,
+                                       SkPDFObject* substitute) {
+    SkASSERT(original != substitute);
+    SkASSERT(!fSubstituteMap.find(original));
+    fSubstituteMap.set(original, SkRef(substitute));
+}
+
+SkPDFObject* SkPDFSubstituteMap::getSubstitute(SkPDFObject* object) const {
+    SkPDFObject** found = fSubstituteMap.find(object);
+    return found ? *found : object;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool SkPDFObjNumMap::addObject(SkPDFObject* obj) {
+    if (fObjectNumbers.find(obj)) {
+        return false;
+    }
+    fObjectNumbers.set(obj, fObjectNumbers.count() + 1);
+    fObjects.push(obj);
+    return true;
+}
+
+int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const {
+    int32_t* objectNumberFound = fObjectNumbers.find(obj);
+    SkASSERT(objectNumberFound);
+    return *objectNumberFound;
+}
+