1 /* 2 * Copyright 2010 The Android Open Source Project 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkPDFTypes_DEFINED 9 #define SkPDFTypes_DEFINED 10 11 #include "SkRefCnt.h" 12 #include "SkScalar.h" 13 #include "SkTHash.h" 14 #include "SkTo.h" 15 #include "SkTypes.h" 16 #include "SkMakeUnique.h" 17 18 #include <new> 19 #include <type_traits> 20 #include <utility> 21 #include <vector> 22 #include <memory> 23 24 class SkData; 25 class SkPDFArray; 26 27 class SkPDFDict; 28 class SkPDFDocument; 29 class SkPDFObject; 30 class SkPDFUnion; 31 class SkStreamAsset; 32 class SkString; 33 class SkWStream; 34 struct SkPDFObjectSerializer; 35 36 struct SkPDFIndirectReference { 37 int fValue = -1; 38 explicit operator bool() { return fValue != -1; } 39 }; 40 41 inline static bool operator==(SkPDFIndirectReference u, SkPDFIndirectReference v) { 42 return u.fValue == v.fValue; 43 } 44 45 inline static bool operator!=(SkPDFIndirectReference u, SkPDFIndirectReference v) { 46 return u.fValue != v.fValue; 47 } 48 49 /** \class SkPDFObject 50 51 A PDF Object is the base class for primitive elements in a PDF file. A 52 common subtype is used to ease the use of indirect object references, 53 which are common in the PDF format. 54 55 */ 56 class SkPDFObject { 57 public: 58 SkPDFObject() = default; 59 60 /** Subclasses must implement this method to print the object to the 61 * PDF file. 62 * @param catalog The object catalog to use. 63 * @param stream The writable output stream to send the output to. 64 */ 65 virtual void emitObject(SkWStream* stream) const = 0; 66 67 virtual ~SkPDFObject() = default; 68 69 private: 70 SkPDFObject(SkPDFObject&&) = delete; 71 SkPDFObject(const SkPDFObject&) = delete; 72 SkPDFObject& operator=(SkPDFObject&&) = delete; 73 SkPDFObject& operator=(const SkPDFObject&) = delete; 74 }; 75 76 //////////////////////////////////////////////////////////////////////////////// 77 78 /** \class SkPDFArray 79 80 An array object in a PDF. 81 */ 82 class SkPDFArray final : public SkPDFObject { 83 public: 84 /** Create a PDF array. Maximum length is 8191. 85 */ 86 SkPDFArray(); 87 ~SkPDFArray() override; 88 89 // The SkPDFObject interface. 90 void emitObject(SkWStream* stream) const override; 91 92 /** The size of the array. 93 */ 94 size_t size() const; 95 96 /** Preallocate space for the given number of entries. 97 * @param length The number of array slots to preallocate. 98 */ 99 void reserve(int length); 100 101 /** Appends a value to the end of the array. 102 * @param value The value to add to the array. 103 */ 104 void appendInt(int32_t); 105 void appendColorComponent(uint8_t); 106 void appendBool(bool); 107 void appendScalar(SkScalar); 108 void appendName(const char[]); 109 void appendName(SkString); 110 void appendString(const char[]); 111 void appendString(SkString); 112 void appendObject(std::unique_ptr<SkPDFObject>&&); 113 void appendRef(SkPDFIndirectReference); 114 115 private: 116 std::vector<SkPDFUnion> fValues; 117 void append(SkPDFUnion&& value); 118 }; 119 120 static inline void SkPDFArray_Append(SkPDFArray* a, int v) { a->appendInt(v); } 121 122 static inline void SkPDFArray_Append(SkPDFArray* a, SkScalar v) { a->appendScalar(v); } 123 124 template <typename T, typename... Args> 125 static inline void SkPDFArray_Append(SkPDFArray* a, T v, Args... args) { 126 SkPDFArray_Append(a, v); 127 SkPDFArray_Append(a, args...); 128 } 129 130 static inline void SkPDFArray_Append(SkPDFArray* a) {} 131 132 template <typename... Args> 133 static inline std::unique_ptr<SkPDFArray> SkPDFMakeArray(Args... args) { 134 std::unique_ptr<SkPDFArray> ret(new SkPDFArray()); 135 ret->reserve(sizeof...(Args)); 136 SkPDFArray_Append(ret.get(), args...); 137 return ret; 138 } 139 140 /** \class SkPDFDict 141 142 A dictionary object in a PDF. 143 */ 144 class SkPDFDict final : public SkPDFObject { 145 public: 146 /** Create a PDF dictionary. 147 * @param type The value of the Type entry, nullptr for no type. 148 */ 149 explicit SkPDFDict(const char type[] = nullptr); 150 151 ~SkPDFDict() override; 152 153 // The SkPDFObject interface. 154 void emitObject(SkWStream* stream) const override; 155 156 /** The size of the dictionary. 157 */ 158 size_t size() const; 159 160 /** Preallocate space for n key-value pairs */ 161 void reserve(int n); 162 163 /** Add the value to the dictionary with the given key. 164 * @param key The text of the key for this dictionary entry. 165 * @param value The value for this dictionary entry. 166 */ 167 void insertObject(const char key[], std::unique_ptr<SkPDFObject>&&); 168 void insertObject(SkString, std::unique_ptr<SkPDFObject>&&); 169 void insertRef(const char key[], SkPDFIndirectReference); 170 void insertRef(SkString, SkPDFIndirectReference); 171 172 /** Add the value to the dictionary with the given key. 173 * @param key The text of the key for this dictionary entry. 174 * @param value The value for this dictionary entry. 175 */ 176 void insertBool(const char key[], bool value); 177 void insertInt(const char key[], int32_t value); 178 void insertInt(const char key[], size_t value); 179 void insertScalar(const char key[], SkScalar value); 180 void insertColorComponentF(const char key[], SkScalar value); 181 void insertName(const char key[], const char nameValue[]); 182 void insertName(const char key[], SkString nameValue); 183 void insertString(const char key[], const char value[]); 184 void insertString(const char key[], SkString value); 185 186 private: 187 std::vector<std::pair<SkPDFUnion, SkPDFUnion>> fRecords; 188 }; 189 190 static inline std::unique_ptr<SkPDFDict> SkPDFMakeDict(const char* type = nullptr) { 191 return std::unique_ptr<SkPDFDict>(new SkPDFDict(type)); 192 } 193 194 #ifdef SK_PDF_LESS_COMPRESSION 195 static constexpr bool kSkPDFDefaultDoDeflate = false; 196 #else 197 static constexpr bool kSkPDFDefaultDoDeflate = true; 198 #endif 199 200 SkPDFIndirectReference SkPDFStreamOut(std::unique_ptr<SkPDFDict> dict, 201 std::unique_ptr<SkStreamAsset> stream, 202 SkPDFDocument* doc, 203 bool deflate = kSkPDFDefaultDoDeflate); 204 #endif 205