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