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