1 // Copyright 2018 Google LLC. 2 // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. 3 #ifndef SkPDFUnion_DEFINED 4 #define SkPDFUnion_DEFINED 5 6 #include "SkPDFTypes.h" 7 8 template <class T> 9 class SkStorageFor { 10 public: get()11 const T& get() const { return *reinterpret_cast<const T*>(&fStore); } get()12 T& get() { return *reinterpret_cast<T*>(&fStore); } 13 // Up to caller to keep track of status. init(Args &&...args)14 template<class... Args> void init(Args&&... args) { 15 new (&this->get()) T(std::forward<Args>(args)...); 16 } destroy()17 void destroy() { this->get().~T(); } 18 private: 19 typename std::aligned_storage<sizeof(T), alignof(T)>::type fStore; 20 }; 21 22 // Exposed for unit testing. 23 void SkPDFWriteString(SkWStream* wStream, const char* cin, size_t len); 24 25 //////////////////////////////////////////////////////////////////////////////// 26 27 /** 28 A SkPDFUnion is a non-virtualized implementation of the 29 non-compound, non-specialized PDF Object types: Name, String, 30 Number, Boolean. 31 */ 32 class SkPDFUnion { 33 public: 34 // Move contstructor and assignment operator destroy the argument 35 // and steal their references (if needed). 36 SkPDFUnion(SkPDFUnion&& other); 37 SkPDFUnion& operator=(SkPDFUnion&& other); 38 39 ~SkPDFUnion(); 40 41 /** The following nine functions are the standard way of creating 42 SkPDFUnion objects. */ 43 44 static SkPDFUnion Int(int32_t); 45 Int(size_t v)46 static SkPDFUnion Int(size_t v) { return SkPDFUnion::Int(SkToS32(v)); } 47 48 static SkPDFUnion Bool(bool); 49 50 static SkPDFUnion Scalar(SkScalar); 51 52 static SkPDFUnion ColorComponent(uint8_t); 53 54 static SkPDFUnion ColorComponentF(float); 55 56 /** These two functions do NOT take ownership of char*, and do NOT 57 copy the string. Suitable for passing in static const 58 strings. For example: 59 SkPDFUnion n = SkPDFUnion::Name("Length"); 60 SkPDFUnion u = SkPDFUnion::String("Identity"); */ 61 62 /** SkPDFUnion::Name(const char*) assumes that the passed string 63 is already a valid name (that is: it has no control or 64 whitespace characters). This will not copy the name. */ 65 static SkPDFUnion Name(const char*); 66 67 /** SkPDFUnion::String will encode the passed string. This will 68 not copy the name. */ 69 static SkPDFUnion String(const char*); 70 71 /** SkPDFUnion::Name(SkString) does not assume that the 72 passed string is already a valid name and it will escape the 73 string. */ 74 static SkPDFUnion Name(SkString); 75 76 /** SkPDFUnion::String will encode the passed string. */ 77 static SkPDFUnion String(SkString); 78 79 static SkPDFUnion Object(std::unique_ptr<SkPDFObject>); 80 81 static SkPDFUnion Ref(SkPDFIndirectReference); 82 83 /** These two non-virtual methods mirror SkPDFObject's 84 corresponding virtuals. */ 85 void emitObject(SkWStream*) const; 86 87 bool isName() const; 88 89 private: 90 union { 91 int32_t fIntValue; 92 bool fBoolValue; 93 SkScalar fScalarValue; 94 const char* fStaticString; 95 SkStorageFor<SkString> fSkString; 96 SkPDFObject* fObject; 97 }; 98 enum class Type : char { 99 /** It is an error to call emitObject() or addResources() on an 100 kDestroyed object. */ 101 kDestroyed = 0, 102 kInt, 103 kColorComponent, 104 kColorComponentF, 105 kBool, 106 kScalar, 107 kName, 108 kString, 109 kNameSkS, 110 kStringSkS, 111 kObject, 112 kRef, 113 }; 114 Type fType; 115 116 SkPDFUnion(Type); 117 SkPDFUnion(Type, int32_t); 118 SkPDFUnion(Type, bool); 119 SkPDFUnion(Type, SkScalar); 120 SkPDFUnion(Type, SkString); 121 // We do not now need copy constructor and copy assignment, so we 122 // will disable this functionality. 123 SkPDFUnion& operator=(const SkPDFUnion&) = delete; 124 SkPDFUnion(const SkPDFUnion&) = delete; 125 }; 126 static_assert(sizeof(SkString) == sizeof(void*), "SkString_size"); 127 128 #endif // SkPDFUnion_DEFINED 129