1 2 /* 3 * Copyright 2010 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #ifndef SkPDFTypes_DEFINED 11 #define SkPDFTypes_DEFINED 12 13 #include "SkRefCnt.h" 14 #include "SkScalar.h" 15 #include "SkString.h" 16 #include "SkTDArray.h" 17 #include "SkTSet.h" 18 #include "SkTypes.h" 19 20 class SkPDFCatalog; 21 class SkWStream; 22 23 /** \class SkPDFObject 24 25 A PDF Object is the base class for primitive elements in a PDF file. A 26 common subtype is used to ease the use of indirect object references, 27 which are common in the PDF format. 28 */ 29 class SkPDFObject : public SkRefCnt { 30 public: 31 SK_DECLARE_INST_COUNT(SkPDFObject) 32 33 /** Return the size (number of bytes) of this object in the final output 34 * file. Compound objects or objects that are computationally intensive 35 * to output should override this method. 36 * @param catalog The object catalog to use. 37 * @param indirect If true, output an object identifier with the object. 38 */ 39 virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); 40 41 /** For non-primitive objects (i.e. objects defined outside this file), 42 * this method will add to newResourceObjects any objects that this method 43 * depends on, but not already in knownResourceObjects. This operates 44 * recursively so if this object depends on another object and that object 45 * depends on two more, all three objects will be added. 46 * 47 * @param knownResourceObjects The set of resources to be ignored. 48 * @param newResourceObjects The set to append dependant resources to. 49 */ 50 virtual void getResources(const SkTSet<SkPDFObject*>& knownResourceObjects, 51 SkTSet<SkPDFObject*>* newResourceObjects); 52 53 /** Emit this object unless the catalog has a substitute object, in which 54 * case emit that. 55 * @see emitObject 56 */ 57 void emit(SkWStream* stream, SkPDFCatalog* catalog, bool indirect); 58 59 /** Helper function to output an indirect object. 60 * @param catalog The object catalog to use. 61 * @param stream The writable output stream to send the output to. 62 */ 63 void emitIndirectObject(SkWStream* stream, SkPDFCatalog* catalog); 64 65 /** Helper function to find the size of an indirect object. 66 * @param catalog The object catalog to use. 67 */ 68 size_t getIndirectOutputSize(SkPDFCatalog* catalog); 69 70 /** Static helper function to add a resource to a list. The list takes 71 * a reference. 72 * @param resource The resource to add. 73 * @param list The list to add the resource to. 74 */ 75 static void AddResourceHelper(SkPDFObject* resource, 76 SkTDArray<SkPDFObject*>* list); 77 78 /** Static helper function to copy and reference the resources (and all 79 * their subresources) into a new list. 80 * @param resources The resource list. 81 * @param newResourceObjects All the resource objects (recursively) used on 82 * the page are added to this array. This gives 83 * the caller a chance to deduplicate resources 84 * across pages. 85 * @param knownResourceObjects The set of resources to be ignored. 86 */ 87 static void GetResourcesHelper( 88 const SkTDArray<SkPDFObject*>* resources, 89 const SkTSet<SkPDFObject*>& knownResourceObjects, 90 SkTSet<SkPDFObject*>* newResourceObjects); 91 92 protected: 93 /** Subclasses must implement this method to print the object to the 94 * PDF file. 95 * @param catalog The object catalog to use. 96 * @param indirect If true, output an object identifier with the object. 97 * @param stream The writable output stream to send the output to. 98 */ 99 virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, 100 bool indirect) = 0; 101 102 typedef SkRefCnt INHERITED; 103 }; 104 105 /** \class SkPDFObjRef 106 107 An indirect reference to a PDF object. 108 */ 109 class SkPDFObjRef : public SkPDFObject { 110 public: 111 SK_DECLARE_INST_COUNT(SkPDFObjRef) 112 113 /** Create a reference to an existing SkPDFObject. 114 * @param obj The object to reference. 115 */ 116 explicit SkPDFObjRef(SkPDFObject* obj); 117 virtual ~SkPDFObjRef(); 118 119 // The SkPDFObject interface. 120 virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, 121 bool indirect); 122 virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); 123 124 private: 125 SkAutoTUnref<SkPDFObject> fObj; 126 127 typedef SkPDFObject INHERITED; 128 }; 129 130 /** \class SkPDFInt 131 132 An integer object in a PDF. 133 */ 134 class SkPDFInt : public SkPDFObject { 135 public: 136 SK_DECLARE_INST_COUNT(SkPDFInt) 137 138 /** Create a PDF integer (usually for indirect reference purposes). 139 * @param value An integer value between 2^31 - 1 and -2^31. 140 */ 141 explicit SkPDFInt(int32_t value); 142 virtual ~SkPDFInt(); 143 144 // The SkPDFObject interface. 145 virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, 146 bool indirect); 147 148 private: 149 int32_t fValue; 150 151 typedef SkPDFObject INHERITED; 152 }; 153 154 /** \class SkPDFBool 155 156 An boolean value in a PDF. 157 */ 158 class SkPDFBool : public SkPDFObject { 159 public: 160 SK_DECLARE_INST_COUNT(SkPDFBool) 161 162 /** Create a PDF boolean. 163 * @param value true or false. 164 */ 165 explicit SkPDFBool(bool value); 166 virtual ~SkPDFBool(); 167 168 // The SkPDFObject interface. 169 virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, 170 bool indirect); 171 virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); 172 173 private: 174 bool fValue; 175 176 typedef SkPDFObject INHERITED; 177 }; 178 179 /** \class SkPDFScalar 180 181 A real number object in a PDF. 182 */ 183 class SkPDFScalar : public SkPDFObject { 184 public: 185 SK_DECLARE_INST_COUNT(SkPDFScalar) 186 187 /** Create a PDF real number. 188 * @param value A real value. 189 */ 190 explicit SkPDFScalar(SkScalar value); 191 virtual ~SkPDFScalar(); 192 193 static void Append(SkScalar value, SkWStream* stream); 194 195 // The SkPDFObject interface. 196 virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, 197 bool indirect); 198 199 private: 200 SkScalar fValue; 201 202 typedef SkPDFObject INHERITED; 203 }; 204 205 /** \class SkPDFString 206 207 A string object in a PDF. 208 */ 209 class SkPDFString : public SkPDFObject { 210 public: 211 SK_DECLARE_INST_COUNT(SkPDFString) 212 213 /** Create a PDF string. Maximum length (in bytes) is 65,535. 214 * @param value A string value. 215 */ 216 explicit SkPDFString(const char value[]); 217 explicit SkPDFString(const SkString& value); 218 219 /** Create a PDF string. Maximum length (in bytes) is 65,535. 220 * @param value A string value. 221 * @param len The length of value. 222 * @param wideChars Indicates if the top byte in value is significant and 223 * should be encoded (true) or not (false). 224 */ 225 SkPDFString(const uint16_t* value, size_t len, bool wideChars); 226 virtual ~SkPDFString(); 227 228 // The SkPDFObject interface. 229 virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, 230 bool indirect); 231 virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); 232 233 static SkString FormatString(const char* input, size_t len); 234 static SkString FormatString(const uint16_t* input, size_t len, 235 bool wideChars); 236 private: 237 static const size_t kMaxLen = 65535; 238 239 const SkString fValue; 240 241 static SkString DoFormatString(const void* input, size_t len, 242 bool wideInput, bool wideOutput); 243 244 typedef SkPDFObject INHERITED; 245 }; 246 247 /** \class SkPDFName 248 249 A name object in a PDF. 250 */ 251 class SkPDFName : public SkPDFObject { 252 public: 253 SK_DECLARE_INST_COUNT(SkPDFName) 254 255 /** Create a PDF name object. Maximum length is 127 bytes. 256 * @param value The name. 257 */ 258 explicit SkPDFName(const char name[]); 259 explicit SkPDFName(const SkString& name); 260 virtual ~SkPDFName(); 261 262 bool operator==(const SkPDFName& b) const; 263 264 // The SkPDFObject interface. 265 virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, 266 bool indirect); 267 virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); 268 269 private: 270 static const size_t kMaxLen = 127; 271 272 const SkString fValue; 273 274 static SkString FormatName(const SkString& input); 275 276 typedef SkPDFObject INHERITED; 277 }; 278 279 /** \class SkPDFArray 280 281 An array object in a PDF. 282 */ 283 class SkPDFArray : public SkPDFObject { 284 public: 285 SK_DECLARE_INST_COUNT(SkPDFArray) 286 287 /** Create a PDF array. Maximum length is 8191. 288 */ 289 SkPDFArray(); 290 virtual ~SkPDFArray(); 291 292 // The SkPDFObject interface. 293 virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, 294 bool indirect); 295 virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); 296 297 /** The size of the array. 298 */ 299 int size() { return fValue.count(); } 300 301 /** Preallocate space for the given number of entries. 302 * @param length The number of array slots to preallocate. 303 */ 304 void reserve(int length); 305 306 /** Returns the object at the given offset in the array. 307 * @param index The index into the array to retrieve. 308 */ 309 SkPDFObject* getAt(int index) { return fValue[index]; } 310 311 /** Set the object at the given offset in the array. Ref's value. 312 * @param index The index into the array to set. 313 * @param value The value to add to the array. 314 * @return The value argument is returned. 315 */ 316 SkPDFObject* setAt(int index, SkPDFObject* value); 317 318 /** Append the object to the end of the array and increments its ref count. 319 * @param value The value to add to the array. 320 * @return The value argument is returned. 321 */ 322 SkPDFObject* append(SkPDFObject* value); 323 324 /** Creates a SkPDFInt object and appends it to the array. 325 * @param value The value to add to the array. 326 */ 327 void appendInt(int32_t value); 328 329 /** Creates a SkPDFScalar object and appends it to the array. 330 * @param value The value to add to the array. 331 */ 332 void appendScalar(SkScalar value); 333 334 /** Creates a SkPDFName object and appends it to the array. 335 * @param value The value to add to the array. 336 */ 337 void appendName(const char name[]); 338 339 private: 340 static const int kMaxLen = 8191; 341 SkTDArray<SkPDFObject*> fValue; 342 343 typedef SkPDFObject INHERITED; 344 }; 345 346 /** \class SkPDFDict 347 348 A dictionary object in a PDF. 349 */ 350 class SkPDFDict : public SkPDFObject { 351 public: 352 SK_DECLARE_INST_COUNT(SkPDFDict) 353 354 /** Create a PDF dictionary. Maximum number of entries is 4095. 355 */ 356 SkPDFDict(); 357 358 /** Create a PDF dictionary with a Type entry. 359 * @param type The value of the Type entry. 360 */ 361 explicit SkPDFDict(const char type[]); 362 363 virtual ~SkPDFDict(); 364 365 // The SkPDFObject interface. 366 virtual void emitObject(SkWStream* stream, SkPDFCatalog* catalog, 367 bool indirect); 368 virtual size_t getOutputSize(SkPDFCatalog* catalog, bool indirect); 369 370 /** The size of the dictionary. 371 */ 372 int size() const; 373 374 /** Add the value to the dictionary with the given key. Refs value. 375 * @param key The key for this dictionary entry. 376 * @param value The value for this dictionary entry. 377 * @return The value argument is returned. 378 */ 379 SkPDFObject* insert(SkPDFName* key, SkPDFObject* value); 380 381 /** Add the value to the dictionary with the given key. Refs value. The 382 * method will create the SkPDFName object. 383 * @param key The text of the key for this dictionary entry. 384 * @param value The value for this dictionary entry. 385 * @return The value argument is returned. 386 */ 387 SkPDFObject* insert(const char key[], SkPDFObject* value); 388 389 /** Add the int to the dictionary with the given key. 390 * @param key The text of the key for this dictionary entry. 391 * @param value The int value for this dictionary entry. 392 */ 393 void insertInt(const char key[], int32_t value); 394 395 /** 396 * Calls insertInt() but asserts in debug builds that the value can be represented 397 * by an int32_t. 398 */ 399 void insertInt(const char key[], size_t value) { 400 this->insertInt(key, SkToS32(value)); 401 } 402 403 /** Add the scalar to the dictionary with the given key. 404 * @param key The text of the key for this dictionary entry. 405 * @param value The scalar value for this dictionary entry. 406 */ 407 void insertScalar(const char key[], SkScalar value); 408 409 /** Add the name to the dictionary with the given key. 410 * @param key The text of the key for this dictionary entry. 411 * @param name The name for this dictionary entry. 412 */ 413 void insertName(const char key[], const char name[]); 414 415 /** Add the name to the dictionary with the given key. 416 * @param key The text of the key for this dictionary entry. 417 * @param name The name for this dictionary entry. 418 */ 419 void insertName(const char key[], const SkString& name) { 420 this->insertName(key, name.c_str()); 421 } 422 423 /** Remove all entries from the dictionary. 424 */ 425 void clear(); 426 427 protected: 428 /** Use to remove a single key from the dictionary. 429 */ 430 void remove(const char key[]); 431 432 /** Insert references to all of the key-value pairs from the other 433 * dictionary into this one. 434 */ 435 void mergeFrom(const SkPDFDict& other); 436 437 private: 438 struct Rec { 439 SkPDFName* key; 440 SkPDFObject* value; 441 Rec(SkPDFName* k, SkPDFObject* v) : key(k), value(v) {} 442 }; 443 444 static const int kMaxLen = 4095; 445 446 mutable SkMutex fMutex; // protects modifications to fValue 447 SkTDArray<struct Rec> fValue; 448 449 SkPDFObject* append(SkPDFName* key, SkPDFObject* value); 450 451 typedef SkPDFObject INHERITED; 452 }; 453 454 #endif 455