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 9 #ifndef SkPDFTypes_DEFINED 10 #define SkPDFTypes_DEFINED 11 12 #include "SkRefCnt.h" 13 #include "SkScalar.h" 14 #include "SkString.h" 15 #include "SkTDArray.h" 16 #include "SkTHash.h" 17 #include "SkTypes.h" 18 19 class SkPDFObjNumMap; 20 class SkPDFObject; 21 class SkPDFSubstituteMap; 22 class SkWStream; 23 24 /** \class SkPDFObject 25 26 A PDF Object is the base class for primitive elements in a PDF file. A 27 common subtype is used to ease the use of indirect object references, 28 which are common in the PDF format. 29 30 */ 31 class SkPDFObject : public SkRefCnt { 32 public: 33 SK_DECLARE_INST_COUNT(SkPDFObject); 34 35 /** Subclasses must implement this method to print the object to the 36 * PDF file. 37 * @param catalog The object catalog to use. 38 * @param stream The writable output stream to send the output to. 39 */ 40 // TODO(halcanary): make this method const 41 virtual void emitObject(SkWStream* stream, 42 const SkPDFObjNumMap& objNumMap, 43 const SkPDFSubstituteMap& substitutes) = 0; 44 45 /** 46 * Adds all transitive dependencies of this object to the 47 * catalog. Implementations should respect the catalog's object 48 * substitution map. 49 */ addResources(SkPDFObjNumMap * catalog,const SkPDFSubstituteMap & substitutes)50 virtual void addResources(SkPDFObjNumMap* catalog, 51 const SkPDFSubstituteMap& substitutes) const {} 52 53 private: 54 typedef SkRefCnt INHERITED; 55 }; 56 57 //////////////////////////////////////////////////////////////////////////////// 58 59 /** 60 A SkPDFUnion is a non-virtualized implementation of the 61 non-compound, non-specialized PDF Object types: Name, String, 62 Number, Boolean. 63 */ 64 class SkPDFUnion { 65 public: 66 // u.move() is analogous to std::move(u). It returns an rvalue. move()67 SkPDFUnion move() { return static_cast<SkPDFUnion&&>(*this); } 68 // Move contstructor and assignemnt operator destroy the argument 69 // and steal their references (if needed). 70 SkPDFUnion(SkPDFUnion&& other); 71 SkPDFUnion& operator=(SkPDFUnion&& other); 72 73 ~SkPDFUnion(); 74 75 /** The following nine functions are the standard way of creating 76 SkPDFUnion objects. */ 77 78 static SkPDFUnion Int(int32_t); 79 80 static SkPDFUnion Int(size_t); 81 82 static SkPDFUnion Bool(bool); 83 84 static SkPDFUnion Scalar(SkScalar); 85 86 /** These two functions do NOT take ownership of ptr, and do NOT 87 copy the string. Suitable for passing in static const 88 strings. For example: 89 SkPDFUnion n = SkPDFUnion::Name("Length"); 90 SkPDFUnion u = SkPDFUnion::String("Identity"); */ 91 92 /** SkPDFUnion::Name(const char*) assumes that the passed string 93 is already a valid name (that is: it has no control or 94 whitespace characters). This will not copy the name. */ 95 static SkPDFUnion Name(const char*); 96 97 /** SkPDFUnion::String will encode the passed string. This will 98 not copy the name. */ 99 static SkPDFUnion String(const char*); 100 101 /** SkPDFUnion::Name(const SkString&) does not assume that the 102 passed string is already a valid name and it will escape the 103 string. */ 104 static SkPDFUnion Name(const SkString&); 105 106 /** SkPDFUnion::String will encode the passed string. */ 107 static SkPDFUnion String(const SkString&); 108 109 /** This function DOES take ownership of the object. E.g. 110 SkAutoTUnref<SkPDFDict> dict(new SkPDFDict); 111 dict->insert(.....); 112 SkPDFUnion u = SkPDFUnion::Object(dict.detach()) */ 113 static SkPDFUnion Object(SkPDFObject*); 114 115 /** This function DOES take ownership of the object. E.g. 116 SkAutoTUnref<SkPDFBitmap> image( 117 SkPDFBitmap::Create(fCanon, bitmap)); 118 SkPDFUnion u = SkPDFUnion::ObjRef(image.detach()) */ 119 static SkPDFUnion ObjRef(SkPDFObject*); 120 121 /** These two non-virtual methods mirror SkPDFObject's 122 corresponding virtuals. */ 123 void emitObject(SkWStream*, 124 const SkPDFObjNumMap&, 125 const SkPDFSubstituteMap&) const; 126 void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const; 127 128 bool isName() const; 129 130 private: 131 union { 132 int32_t fIntValue; 133 bool fBoolValue; 134 SkScalar fScalarValue; 135 const char* fStaticString; 136 char fSkString[sizeof(SkString)]; 137 SkPDFObject* fObject; 138 }; 139 enum class Type : char { 140 /** It is an error to call emitObject() or addResources() on an 141 kDestroyed object. */ 142 kDestroyed = 0, 143 kInt, 144 kBool, 145 kScalar, 146 kName, 147 kString, 148 kNameSkS, 149 kStringSkS, 150 kObjRef, 151 kObject, 152 }; 153 Type fType; 154 155 SkPDFUnion(Type); 156 // We do not now need copy constructor and copy assignment, so we 157 // will disable this functionality. 158 SkPDFUnion& operator=(const SkPDFUnion&) = delete; 159 SkPDFUnion(const SkPDFUnion&) = delete; 160 }; 161 SK_COMPILE_ASSERT(sizeof(SkString) == sizeof(void*), SkString_size); 162 163 //////////////////////////////////////////////////////////////////////////////// 164 165 #if 0 // Enable if needed. 166 /** This class is a SkPDFUnion with SkPDFObject virtuals attached. 167 The only use case of this is when a non-compound PDF object is 168 referenced indirectly. */ 169 class SkPDFAtom : public SkPDFObject { 170 public: 171 void emitObject(SkWStream* stream, 172 const SkPDFObjNumMap& objNumMap, 173 const SkPDFSubstituteMap& substitutes) final; 174 void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const final; 175 SkPDFAtom(SkPDFUnion&& v) : fValue(v.move()) {} 176 177 private: 178 const SkPDFUnion fValue; 179 typedef SkPDFObject INHERITED; 180 }; 181 #endif // 0 182 183 //////////////////////////////////////////////////////////////////////////////// 184 185 /** \class SkPDFArray 186 187 An array object in a PDF. 188 */ 189 class SkPDFArray : public SkPDFObject { 190 public: 191 SK_DECLARE_INST_COUNT(SkPDFArray) 192 193 static const int kMaxLen = 8191; 194 195 /** Create a PDF array. Maximum length is 8191. 196 */ 197 SkPDFArray(); 198 virtual ~SkPDFArray(); 199 200 // The SkPDFObject interface. 201 void emitObject(SkWStream* stream, 202 const SkPDFObjNumMap& objNumMap, 203 const SkPDFSubstituteMap& substitutes) override; 204 void addResources(SkPDFObjNumMap*, 205 const SkPDFSubstituteMap&) const override; 206 207 /** The size of the array. 208 */ 209 int size() const; 210 211 /** Preallocate space for the given number of entries. 212 * @param length The number of array slots to preallocate. 213 */ 214 void reserve(int length); 215 216 /** Appends a value to the end of the array. 217 * @param value The value to add to the array. 218 */ 219 void appendInt(int32_t); 220 void appendBool(bool); 221 void appendScalar(SkScalar); 222 void appendName(const char[]); 223 void appendName(const SkString&); 224 void appendString(const char[]); 225 void appendString(const SkString&); 226 /** appendObject and appendObjRef take ownership of the passed object */ 227 void appendObject(SkPDFObject*); 228 void appendObjRef(SkPDFObject*); 229 230 private: 231 SkTDArray<SkPDFUnion> fValues; 232 void append(SkPDFUnion&& value); 233 typedef SkPDFObject INHERITED; 234 }; 235 236 /** \class SkPDFDict 237 238 A dictionary object in a PDF. 239 */ 240 class SkPDFDict : public SkPDFObject { 241 public: 242 SK_DECLARE_INST_COUNT(SkPDFDict) 243 244 /** Create a PDF dictionary. Maximum number of entries is 4095. 245 */ 246 SkPDFDict(); 247 248 /** Create a PDF dictionary with a Type entry. 249 * @param type The value of the Type entry. 250 */ 251 explicit SkPDFDict(const char type[]); 252 253 virtual ~SkPDFDict(); 254 255 // The SkPDFObject interface. 256 void emitObject(SkWStream* stream, 257 const SkPDFObjNumMap& objNumMap, 258 const SkPDFSubstituteMap& substitutes) override; 259 void addResources(SkPDFObjNumMap*, 260 const SkPDFSubstituteMap&) const override; 261 262 /** The size of the dictionary. 263 */ 264 int size() const; 265 266 /** Add the value to the dictionary with the given key. Takes 267 * ownership of the object. 268 * @param key The text of the key for this dictionary entry. 269 * @param value The value for this dictionary entry. 270 */ 271 void insertObject(const char key[], SkPDFObject* value); 272 void insertObject(const SkString& key, SkPDFObject* value); 273 void insertObjRef(const char key[], SkPDFObject* value); 274 void insertObjRef(const SkString& key, SkPDFObject* value); 275 276 /** Add the value to the dictionary with the given key. 277 * @param key The text of the key for this dictionary entry. 278 * @param value The value for this dictionary entry. 279 */ 280 void insertBool(const char key[], bool value); 281 void insertInt(const char key[], int32_t value); 282 void insertInt(const char key[], size_t value); 283 void insertScalar(const char key[], SkScalar value); 284 void insertName(const char key[], const char nameValue[]); 285 void insertName(const char key[], const SkString& nameValue); 286 void insertString(const char key[], const char value[]); 287 void insertString(const char key[], const SkString& value); 288 289 /** Remove all entries from the dictionary. 290 */ 291 void clear(); 292 293 private: 294 struct Record { 295 SkPDFUnion fKey; 296 SkPDFUnion fValue; 297 }; 298 SkTDArray<Record> fRecords; 299 static const int kMaxLen = 4095; 300 301 void set(SkPDFUnion&& name, SkPDFUnion&& value); 302 303 typedef SkPDFObject INHERITED; 304 }; 305 306 //////////////////////////////////////////////////////////////////////////////// 307 308 /** \class SkPDFObjNumMap 309 310 The PDF Object Number Map manages object numbers. It is used to 311 create the PDF cross reference table. 312 */ 313 class SkPDFObjNumMap : SkNoncopyable { 314 public: 315 /** Add the passed object to the catalog. 316 * @param obj The object to add. 317 * @return True iff the object was not already added to the catalog. 318 */ 319 bool addObject(SkPDFObject* obj); 320 321 /** Get the object number for the passed object. 322 * @param obj The object of interest. 323 */ 324 int32_t getObjectNumber(SkPDFObject* obj) const; 325 objects()326 const SkTDArray<SkPDFObject*>& objects() const { return fObjects; } 327 328 private: 329 SkTDArray<SkPDFObject*> fObjects; 330 SkTHashMap<SkPDFObject*, int32_t> fObjectNumbers; 331 }; 332 333 //////////////////////////////////////////////////////////////////////////////// 334 335 /** \class SkPDFSubstituteMap 336 337 The PDF Substitute Map manages substitute objects and owns the 338 substitutes. 339 */ 340 class SkPDFSubstituteMap : SkNoncopyable { 341 public: 342 ~SkPDFSubstituteMap(); 343 /** Set substitute object for the passed object. 344 Refs substitute. 345 */ 346 void setSubstitute(SkPDFObject* original, SkPDFObject* substitute); 347 348 /** Find and return any substitute object set for the passed object. If 349 * there is none, return the passed object. 350 */ 351 SkPDFObject* getSubstitute(SkPDFObject* object) const; 352 operator()353 SkPDFObject* operator()(SkPDFObject* o) const { 354 return this->getSubstitute(o); 355 } 356 357 private: 358 SkTHashMap<SkPDFObject*, SkPDFObject*> fSubstituteMap; 359 }; 360 361 #endif 362