SkPDF: even more PDFIndirectRefs

  * SkPDFUnion.h hidden.
  * SkPDFObjectSerializer::serializeObject gone.
  * SkPDFDocument::serialize gone
  * SkPDFMetadata::MakeXMPObject return PDFIndirectRef
  * SkPDFTag rewritten from scratch.
  * SkPDFObject::addResources virtual gone.
  * SkPDFObject::drop virtual gone.
  * SkPDFArray::appendObjRef gone.
  * SkPDFDict::insertObjRef gone.
  * SkPDFDict::Record becomes std::pair
  * SkPDFObjNumMap gone;
  * SkPDFObject::fIndirectReference gone;

Bug: skia:8630
Change-Id: I7425eef30548b54f10fbfe96dd502800cb150caf
Reviewed-on: https://skia-review.googlesource.com/c/178935
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Hal Canary <halcanary@google.com>
diff --git a/src/pdf/SkPDFUnion.h b/src/pdf/SkPDFUnion.h
new file mode 100644
index 0000000..d46a5a6
--- /dev/null
+++ b/src/pdf/SkPDFUnion.h
@@ -0,0 +1,128 @@
+// Copyright 2018 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+#ifndef SkPDFUnion_DEFINED
+#define SkPDFUnion_DEFINED
+
+#include "SkPDFTypes.h"
+
+template <class T>
+class SkStorageFor {
+public:
+    const T& get() const { return *reinterpret_cast<const T*>(&fStore); }
+    T& get() { return *reinterpret_cast<T*>(&fStore); }
+    // Up to caller to keep track of status.
+    template<class... Args> void init(Args&&... args) {
+        new (&this->get()) T(std::forward<Args>(args)...);
+    }
+    void destroy() { this->get().~T(); }
+private:
+    typename std::aligned_storage<sizeof(T), alignof(T)>::type fStore;
+};
+
+// Exposed for unit testing.
+void SkPDFWriteString(SkWStream* wStream, const char* cin, size_t len);
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+   A SkPDFUnion is a non-virtualized implementation of the
+   non-compound, non-specialized PDF Object types: Name, String,
+   Number, Boolean.
+ */
+class SkPDFUnion {
+public:
+    // Move contstructor and assignemnt operator destroy the argument
+    // and steal their references (if needed).
+    SkPDFUnion(SkPDFUnion&& other);
+    SkPDFUnion& operator=(SkPDFUnion&& other);
+
+    ~SkPDFUnion();
+
+    /** The following nine functions are the standard way of creating
+        SkPDFUnion objects. */
+
+    static SkPDFUnion Int(int32_t);
+
+    static SkPDFUnion Int(size_t v) { return SkPDFUnion::Int(SkToS32(v)); }
+
+    static SkPDFUnion Bool(bool);
+
+    static SkPDFUnion Scalar(SkScalar);
+
+    static SkPDFUnion ColorComponent(uint8_t);
+
+    static SkPDFUnion ColorComponentF(float);
+
+    /** These two functions do NOT take ownership of char*, and do NOT
+        copy the string.  Suitable for passing in static const
+        strings. For example:
+          SkPDFUnion n = SkPDFUnion::Name("Length");
+          SkPDFUnion u = SkPDFUnion::String("Identity"); */
+
+    /** SkPDFUnion::Name(const char*) assumes that the passed string
+        is already a valid name (that is: it has no control or
+        whitespace characters).  This will not copy the name. */
+    static SkPDFUnion Name(const char*);
+
+    /** SkPDFUnion::String will encode the passed string.  This will
+        not copy the name. */
+    static SkPDFUnion String(const char*);
+
+    /** SkPDFUnion::Name(SkString) does not assume that the
+        passed string is already a valid name and it will escape the
+        string. */
+    static SkPDFUnion Name(SkString);
+
+    /** SkPDFUnion::String will encode the passed string. */
+    static SkPDFUnion String(SkString);
+
+    static SkPDFUnion Object(sk_sp<SkPDFObject>);
+
+    static SkPDFUnion Ref(SkPDFIndirectReference);
+
+    /** These two non-virtual methods mirror SkPDFObject's
+        corresponding virtuals. */
+    void emitObject(SkWStream*) const;
+
+    bool isName() const;
+
+private:
+    union {
+        int32_t fIntValue;
+        bool fBoolValue;
+        SkScalar fScalarValue;
+        const char* fStaticString;
+        SkStorageFor<SkString> fSkString;
+        SkPDFObject* fObject;
+    };
+    enum class Type : char {
+        /** It is an error to call emitObject() or addResources() on an
+            kDestroyed object. */
+        kDestroyed = 0,
+        kInt,
+        kColorComponent,
+        kColorComponentF,
+        kBool,
+        kScalar,
+        kName,
+        kString,
+        kNameSkS,
+        kStringSkS,
+        kObject,
+        kRef,
+    };
+    Type fType;
+
+    SkPDFUnion(Type);
+    SkPDFUnion(Type, int32_t);
+    SkPDFUnion(Type, bool);
+    SkPDFUnion(Type, SkScalar);
+    SkPDFUnion(Type, SkString);
+    // We do not now need copy constructor and copy assignment, so we
+    // will disable this functionality.
+    SkPDFUnion& operator=(const SkPDFUnion&) = delete;
+    SkPDFUnion(const SkPDFUnion&) = delete;
+};
+static_assert(sizeof(SkString) == sizeof(void*), "SkString_size");
+
+#endif  // SkPDFUnion_DEFINED