1 /* 2 * Copyright 2013 Google Inc. 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 SkPdfNativeObject_DEFINED 9 #define SkPdfNativeObject_DEFINED 10 11 #include <stdint.h> 12 #include <string.h> 13 14 #include "SkMatrix.h" 15 #include "SkPdfConfig.h" 16 #include "SkPdfNativeTokenizer.h" 17 #include "SkPdfNYI.h" 18 #include "SkPdfUtils.h" 19 #include "SkRect.h" 20 #include "SkString.h" 21 #include "SkTDArray.h" 22 #include "SkTDict.h" 23 24 class SkPdfDictionary; 25 class SkPdfStream; 26 class SkPdfAllocator; 27 28 // TODO(edisonn): remove these constants and clean up the code. 29 #define kFilteredStreamBit 0 30 #define kUnfilteredStreamBit 1 31 #define kOwnedStreamBit 2 32 33 /** \class SkPdfNativeObject 34 * 35 * The SkPdfNativeObject class is used to store a pdf object. Classes that inherit it are not 36 * allowed to add fields. 37 * 38 * SkPdfAllocator will allocate them in chunks and will free them in destructor. 39 * 40 * You can allocate one on the stack, as long as you call reset() at the end, and any objects it 41 * points to in an allocator. But if your object is a simple one, like number, then 42 * putting it on stack will be just fine. 43 * 44 */ 45 class SkPdfNativeObject { 46 public: 47 enum ObjectType { 48 // The type will have only one of these values, but for error reporting, we make it an enum 49 // so it can easily report that something was expected to be one of a few types 50 kInvalid_PdfObjectType = 1 << 1, 51 52 kBoolean_PdfObjectType = 1 << 2, 53 kInteger_PdfObjectType = 1 << 3, 54 kReal_PdfObjectType = 1 << 4, 55 _kNumber_PdfObjectType = kInteger_PdfObjectType | kReal_PdfObjectType, 56 kString_PdfObjectType = 1 << 5, 57 kHexString_PdfObjectType = 1 << 6, 58 _kAnyString_PdfObjectType = kString_PdfObjectType | kHexString_PdfObjectType, 59 kName_PdfObjectType = 1 << 7, 60 kKeyword_PdfObjectType = 1 << 8, 61 _kStream_PdfObjectType = 1 << 9, // attached to a Dictionary, do not use 62 kArray_PdfObjectType = 1 << 10, 63 kDictionary_PdfObjectType = 1 << 11, 64 kNull_PdfObjectType = 1 << 12, 65 66 kReference_PdfObjectType = 1 << 13, 67 68 kUndefined_PdfObjectType = 1 << 14, // per 1.4 spec, if the same key appear twice in the 69 // dictionary, the value is undefined. 70 71 _kObject_PdfObjectType = -1, 72 }; 73 74 enum DataType { 75 kEmpty_Data, 76 kFont_Data, 77 kBitmap_Data, 78 }; 79 80 private: 81 // TODO(edisonn): assert reset operations while in rendering! The objects should be reset 82 // only when rendering is completed. 83 uint32_t fInRendering : 1; 84 uint32_t fUnused : 31; 85 86 struct Reference { 87 unsigned int fId; 88 unsigned int fGen; 89 }; 90 91 ObjectType fObjectType; 92 93 union { 94 bool fBooleanValue; 95 int64_t fIntegerValue; 96 // TODO(edisonn): double, float, SkScalar? 97 double fRealValue; 98 NotOwnedString fStr; 99 100 SkTDArray<SkPdfNativeObject*>* fArray; 101 Reference fRef; 102 }; 103 SkTDict<SkPdfNativeObject*>* fMap; 104 105 // TODO(edisonn): rename data with cache 106 void* fData; 107 DataType fDataType; 108 109 #ifdef PDF_TRACK_OBJECT_USAGE 110 // Records if the object was used during rendering/proccessing. It can be used to track 111 // what features are only partially implemented, by looking at what objects have not been 112 // accessed. 113 mutable bool fUsed; 114 #endif // PDF_TRACK_OBJECT_USAGE 115 116 #ifdef PDF_TRACK_STREAM_OFFSETS 117 public: 118 // TODO(edisonn): replace them with char* start, end - and a mechanism to register streams. 119 int fStreamId; 120 int fOffsetStart; 121 int fOffsetEnd; 122 #endif // PDF_TRACK_STREAM_OFFSETS 123 124 public: 125 126 #ifdef PDF_TRACK_STREAM_OFFSETS 127 // TODO(edisonn): remove these ones. streamId()128 int streamId() const { return fStreamId; } offsetStart()129 int offsetStart() const { return fOffsetStart; } offsetEnd()130 int offsetEnd() const { return fOffsetEnd; } 131 #endif // PDF_TRACK_STREAM_OFFSETS 132 SkPdfNativeObject()133 SkPdfNativeObject() : fInRendering(0) 134 , fObjectType(kInvalid_PdfObjectType) 135 , fMap(NULL) 136 , fData(NULL) 137 , fDataType(kEmpty_Data) 138 #ifdef PDF_TRACK_OBJECT_USAGE 139 , fUsed(false) 140 #endif // PDF_TRACK_OBJECT_USAGE 141 142 #ifdef PDF_TRACK_STREAM_OFFSETS 143 , fStreamId(-1) 144 , fOffsetStart(-1) 145 , fOffsetEnd(-1) 146 #endif // PDF_TRACK_STREAM_OFFSETS 147 {} 148 149 // Used to verify if a form is used in rendering, to check for infinite loops. inRendering()150 bool inRendering() const { return fInRendering != 0; } startRendering()151 void startRendering() {fInRendering = 1;} doneRendering()152 void doneRendering() {fInRendering = 0;} 153 154 // Each object can cache one entry associated with it. 155 // for example a SkPdfImage could cache an SkBitmap, of a SkPdfFont, could cache a SkTypeface. hasData(DataType type)156 inline bool hasData(DataType type) { 157 return type == fDataType; 158 } 159 160 // returns the cached value data(DataType type)161 inline void* data(DataType type) { 162 return type == fDataType ? fData : NULL; 163 } 164 165 // Stores something in the cache setData(void * data,DataType type)166 inline void setData(void* data, DataType type) { 167 releaseData(); 168 fDataType = type; 169 fData = data; 170 } 171 172 // destroys the cache 173 void releaseData(); 174 175 // TODO(edisonn): add an assert that reset was called 176 // ~SkPdfNativeObject() { 177 // //reset(); must be called manually! Normally, will be called by allocator destructor. 178 // } 179 180 // Resets a pdf object, deleting all resources directly referenced. 181 // It will not reset/delete indirect resources. 182 // (e.g. it deletes only the array holding pointers to objects, but does not del the objects) reset()183 void reset() { 184 SkPdfMarkObjectUnused(); 185 186 switch (fObjectType) { 187 case kArray_PdfObjectType: 188 delete fArray; 189 break; 190 191 case kDictionary_PdfObjectType: 192 delete fMap; 193 if (isStreamOwned()) { 194 delete[] fStr.fBuffer; 195 fStr.fBuffer = NULL; 196 fStr.fBytes = 0; 197 } 198 break; 199 200 default: 201 break; 202 } 203 fObjectType = kInvalid_PdfObjectType; 204 releaseData(); 205 } 206 207 // returns the object type (Null, Integer, String, Dictionary, ... ) 208 // It does not specify what type of dictionary we have. type()209 ObjectType type() { 210 SkPdfMarkObjectUsed(); 211 212 return fObjectType; 213 } 214 215 // Gives quick access to the buffer's address of a string/keyword/name c_str()216 const char* c_str() const { 217 SkPdfMarkObjectUsed(); 218 219 switch (fObjectType) { 220 case kString_PdfObjectType: 221 case kHexString_PdfObjectType: 222 case kKeyword_PdfObjectType: 223 case kName_PdfObjectType: 224 return (const char*)fStr.fBuffer; 225 226 default: 227 // TODO(edisonn): report/warning/assert? 228 return NULL; 229 } 230 } 231 232 // Gives quick access to the length of a string/keyword/name lenstr()233 size_t lenstr() const { 234 SkPdfMarkObjectUsed(); 235 236 switch (fObjectType) { 237 case kString_PdfObjectType: 238 case kHexString_PdfObjectType: 239 case kKeyword_PdfObjectType: 240 case kName_PdfObjectType: 241 return fStr.fBytes; 242 243 default: 244 // TODO(edisonn): report/warning/assert? 245 return 0; 246 } 247 } 248 249 250 // TODO(edisonn): NYI dateValue()251 SkPdfDate& dateValue() const { 252 static SkPdfDate nyi; 253 return nyi; 254 } 255 256 // TODO(edisonn): NYI functionValue()257 SkPdfFunction& functionValue() const { 258 static SkPdfFunction nyi; 259 return nyi; 260 } 261 262 // TODO(edisonn): NYI fileSpecValue()263 SkPdfFileSpec& fileSpecValue() const { 264 static SkPdfFileSpec nyi; 265 return nyi; 266 } 267 268 // TODO(edisonn): NYI treeValue()269 SkPdfTree& treeValue() const { 270 static SkPdfTree nyi; 271 return nyi; 272 } 273 274 // Creates a Boolean object. Assumes and asserts that it was never initialized. makeBoolean(bool value,SkPdfNativeObject * obj)275 static void makeBoolean(bool value, SkPdfNativeObject* obj) { 276 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 277 278 obj->fObjectType = kBoolean_PdfObjectType; 279 obj->fBooleanValue = value; 280 } 281 makeBoolean(bool value)282 static SkPdfNativeObject makeBoolean(bool value) { 283 SkPdfNativeObject obj; 284 285 obj.fObjectType = kBoolean_PdfObjectType; 286 obj.fBooleanValue = value; 287 return obj; 288 } 289 290 // Creates an Integer object. Assumes and asserts that it was never initialized. makeInteger(int64_t value,SkPdfNativeObject * obj)291 static void makeInteger(int64_t value, SkPdfNativeObject* obj) { 292 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 293 294 obj->fObjectType = kInteger_PdfObjectType; 295 obj->fIntegerValue = value; 296 } 297 298 // Creates a Real object. Assumes and asserts that it was never initialized. makeReal(double value,SkPdfNativeObject * obj)299 static void makeReal(double value, SkPdfNativeObject* obj) { 300 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 301 302 obj->fObjectType = kReal_PdfObjectType; 303 obj->fRealValue = value; 304 } 305 306 // Creates a Null object. Assumes and asserts that it was never initialized. makeNull(SkPdfNativeObject * obj)307 static void makeNull(SkPdfNativeObject* obj) { 308 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 309 310 obj->fObjectType = kNull_PdfObjectType; 311 } 312 makeNull()313 static SkPdfNativeObject makeNull() { 314 SkPdfNativeObject obj; 315 316 obj.fObjectType = kNull_PdfObjectType; 317 return obj; 318 } 319 320 // TODO(edisonn): this might not woirk well in Chrome 321 static SkPdfNativeObject kNull; 322 323 // Creates a Numeric object from a string. Assumes and asserts that it was never initialized. makeNumeric(const unsigned char * start,const unsigned char * end,SkPdfNativeObject * obj)324 static void makeNumeric(const unsigned char* start, const unsigned char* end, 325 SkPdfNativeObject* obj) { 326 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 327 328 // TODO(edisonn): NYI properly 329 // if has dot (impl), or exceeds max int, is real, otherwise is int 330 bool isInt = true; 331 for (const unsigned char* current = start; current < end; current++) { 332 if (*current == '.') { 333 isInt = false; 334 break; 335 } 336 // TODO(edisonn): report parse issue with numbers like "24asdasd123" 337 } 338 if (isInt) { 339 makeInteger(atol((const char*)start), obj); 340 } else { 341 makeReal(atof((const char*)start), obj); 342 } 343 } 344 345 // Creates a Reference object. Assumes and asserts that it was never initialized. makeReference(unsigned int id,unsigned int gen,SkPdfNativeObject * obj)346 static void makeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj) { 347 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 348 349 obj->fObjectType = kReference_PdfObjectType; 350 obj->fRef.fId = id; 351 obj->fRef.fGen = gen; 352 } 353 354 // Creates a Reference object. Resets the object before use. resetAndMakeReference(unsigned int id,unsigned int gen,SkPdfNativeObject * obj)355 static void resetAndMakeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj) { 356 obj->reset(); 357 makeReference(id, gen, obj); 358 } 359 360 // Creates a String object. Assumes and asserts that it was never initialized. makeString(const unsigned char * start,SkPdfNativeObject * obj)361 static void makeString(const unsigned char* start, SkPdfNativeObject* obj) { 362 makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType); 363 } 364 365 // Creates a String object. Assumes and asserts that it was never initialized. makeString(const unsigned char * start,const unsigned char * end,SkPdfNativeObject * obj)366 static void makeString(const unsigned char* start, const unsigned char* end, 367 SkPdfNativeObject* obj) { 368 makeStringCore(start, end - start, obj, kString_PdfObjectType); 369 } 370 371 // Creates a String object. Assumes and asserts that it was never initialized. makeString(const unsigned char * start,size_t bytes,SkPdfNativeObject * obj)372 static void makeString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) { 373 makeStringCore(start, bytes, obj, kString_PdfObjectType); 374 } 375 376 // Creates a HexString object. Assumes and asserts that it was never initialized. makeHexString(const unsigned char * start,SkPdfNativeObject * obj)377 static void makeHexString(const unsigned char* start, SkPdfNativeObject* obj) { 378 makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType); 379 } 380 381 // Creates a HexString object. Assumes and asserts that it was never initialized. makeHexString(const unsigned char * start,const unsigned char * end,SkPdfNativeObject * obj)382 static void makeHexString(const unsigned char* start, const unsigned char* end, 383 SkPdfNativeObject* obj) { 384 makeStringCore(start, end - start, obj, kHexString_PdfObjectType); 385 } 386 387 // Creates a HexString object. Assumes and asserts that it was never initialized. makeHexString(const unsigned char * start,size_t bytes,SkPdfNativeObject * obj)388 static void makeHexString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) { 389 makeStringCore(start, bytes, obj, kHexString_PdfObjectType); 390 } 391 392 // Creates a Name object. Assumes and asserts that it was never initialized. makeName(const unsigned char * start,SkPdfNativeObject * obj)393 static void makeName(const unsigned char* start, SkPdfNativeObject* obj) { 394 makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType); 395 } 396 397 // Creates a Name object. Assumes and asserts that it was never initialized. makeName(const unsigned char * start,const unsigned char * end,SkPdfNativeObject * obj)398 static void makeName(const unsigned char* start, const unsigned char* end, 399 SkPdfNativeObject* obj) { 400 makeStringCore(start, end - start, obj, kName_PdfObjectType); 401 } 402 403 // Creates a Name object. Assumes and asserts that it was never initialized. makeName(const unsigned char * start,size_t bytes,SkPdfNativeObject * obj)404 static void makeName(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) { 405 makeStringCore(start, bytes, obj, kName_PdfObjectType); 406 } 407 408 // Creates a Keyword object. Assumes and asserts that it was never initialized. makeKeyword(const unsigned char * start,SkPdfNativeObject * obj)409 static void makeKeyword(const unsigned char* start, SkPdfNativeObject* obj) { 410 makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType); 411 } 412 413 // Creates a Keyword object. Assumes and asserts that it was never initialized. makeKeyword(const unsigned char * start,const unsigned char * end,SkPdfNativeObject * obj)414 static void makeKeyword(const unsigned char* start, const unsigned char* end, 415 SkPdfNativeObject* obj) { 416 makeStringCore(start, end - start, obj, kKeyword_PdfObjectType); 417 } 418 419 // Creates a Keyword object. Assumes and asserts that it was never initialized. makeKeyword(const unsigned char * start,size_t bytes,SkPdfNativeObject * obj)420 static void makeKeyword(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) { 421 makeStringCore(start, bytes, obj, kKeyword_PdfObjectType); 422 } 423 424 // Creates an empty Array object. Assumes and asserts that it was never initialized. makeEmptyArray(SkPdfNativeObject * obj)425 static void makeEmptyArray(SkPdfNativeObject* obj) { 426 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 427 428 obj->fObjectType = kArray_PdfObjectType; 429 obj->fArray = new SkTDArray<SkPdfNativeObject*>(); 430 } 431 432 // Appends an object into the array. Assumes <this> is an array. appendInArray(SkPdfNativeObject * obj)433 bool appendInArray(SkPdfNativeObject* obj) { 434 SkASSERT(fObjectType == kArray_PdfObjectType); 435 if (fObjectType != kArray_PdfObjectType) { 436 // TODO(edisonn): report/warning/assert? 437 return false; 438 } 439 440 fArray->push(obj); 441 return true; 442 } 443 444 // Returns the size of an array. size()445 size_t size() const { 446 SkPdfMarkObjectUsed(); 447 448 SkASSERT(fObjectType == kArray_PdfObjectType); 449 450 return fArray->count(); 451 } 452 453 // Returns one object of an array, by index. objAtAIndex(int i)454 SkPdfNativeObject* objAtAIndex(int i) { 455 SkPdfMarkObjectUsed(); 456 457 SkASSERT(fObjectType == kArray_PdfObjectType); 458 459 return (*fArray)[i]; 460 } 461 462 // Returns one object of an array, by index. objAtAIndex(int i)463 const SkPdfNativeObject* objAtAIndex(int i) const { 464 SkPdfMarkObjectUsed(); 465 466 SkASSERT(fObjectType == kArray_PdfObjectType); 467 468 return (*fArray)[i]; 469 } 470 471 // Returns one object of an array, by index. 472 SkPdfNativeObject* operator[](int i) { 473 SkPdfMarkObjectUsed(); 474 475 SkASSERT(fObjectType == kArray_PdfObjectType); 476 477 return (*fArray)[i]; 478 } 479 480 const SkPdfNativeObject* operator[](int i) const { 481 SkPdfMarkObjectUsed(); 482 483 SkASSERT(fObjectType == kArray_PdfObjectType); 484 485 return (*fArray)[i]; 486 } 487 488 // Removes the last object in the array. removeLastInArray()489 SkPdfNativeObject* removeLastInArray() { 490 SkPdfMarkObjectUsed(); 491 492 SkASSERT(fObjectType == kArray_PdfObjectType); 493 494 SkPdfNativeObject* ret = NULL; 495 fArray->pop(&ret); 496 497 return ret; 498 } 499 500 // Creates an empty Dictionary object. Assumes and asserts that it was never initialized. makeEmptyDictionary(SkPdfNativeObject * obj)501 static void makeEmptyDictionary(SkPdfNativeObject* obj) { 502 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 503 504 obj->fObjectType = kDictionary_PdfObjectType; 505 obj->fMap = new SkTDict<SkPdfNativeObject*>(1); 506 obj->fStr.fBuffer = NULL; 507 obj->fStr.fBytes = 0; 508 } 509 510 // TODO(edisonn): perf: get all the possible names from spec, and compute a hash function 511 // that would create no overlaps in the same dictionary 512 // or build a tree of chars that when followed goes to a unique id/index/hash 513 // TODO(edisonn): generate constants like kDictFoo, kNameDict_name 514 // which will be used in code 515 // add function SkPdfFastNameKey key(const char* key); 516 // TODO(edisonn): setting the same key twice, will make the value undefined! 517 518 // this[key] = value; set(const SkPdfNativeObject * key,SkPdfNativeObject * value)519 bool set(const SkPdfNativeObject* key, SkPdfNativeObject* value) { 520 SkPdfMarkObjectUsed(); 521 522 SkASSERT(fObjectType == kDictionary_PdfObjectType); 523 SkASSERT(key->fObjectType == kName_PdfObjectType); 524 525 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) { 526 // TODO(edisonn): report/warn/assert? 527 return false; 528 } 529 530 return set(key->fStr.fBuffer, key->fStr.fBytes, value); 531 } 532 533 // this[key] = value; set(const char * key,SkPdfNativeObject * value)534 bool set(const char* key, SkPdfNativeObject* value) { 535 SkPdfMarkObjectUsed(); 536 537 return set((const unsigned char*)key, strlen(key), value); 538 } 539 540 // this[key] = value; set(const unsigned char * key,size_t len,SkPdfNativeObject * value)541 bool set(const unsigned char* key, size_t len, SkPdfNativeObject* value) { 542 SkPdfMarkObjectUsed(); 543 544 SkASSERT(fObjectType == kDictionary_PdfObjectType); 545 546 if (fObjectType != kDictionary_PdfObjectType) { 547 // TODO(edisonn): report/warn/assert. 548 return false; 549 } 550 551 return fMap->set((const char*)key, len, value); 552 } 553 554 // Returns an object from a Dictionary, identified by it's name. get(const SkPdfNativeObject * key)555 SkPdfNativeObject* get(const SkPdfNativeObject* key) { 556 SkPdfMarkObjectUsed(); 557 558 SkASSERT(fObjectType == kDictionary_PdfObjectType); 559 SkASSERT(key->fObjectType == kName_PdfObjectType); 560 561 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) { 562 // TODO(edisonn): report/warn/assert. 563 return NULL; 564 } 565 566 return get(key->fStr.fBuffer, key->fStr.fBytes); 567 } 568 569 // Returns an object from a Dictionary, identified by it's name. get(const char * key)570 SkPdfNativeObject* get(const char* key) { 571 SkPdfMarkObjectUsed(); 572 573 return get((const unsigned char*)key, strlen(key)); 574 } 575 576 // Returns an object from a Dictionary, identified by it's name. get(const unsigned char * key,size_t len)577 SkPdfNativeObject* get(const unsigned char* key, size_t len) { 578 SkPdfMarkObjectUsed(); 579 580 SkASSERT(fObjectType == kDictionary_PdfObjectType); 581 SkASSERT(key); 582 if (fObjectType != kDictionary_PdfObjectType) { 583 // TODO(edisonn): report/warn/assert. 584 return NULL; 585 } 586 SkPdfNativeObject* ret = NULL; 587 fMap->find((const char*)key, len, &ret); 588 589 #ifdef PDF_TRACE 590 SkString _key; 591 _key.append((const char*)key, len); 592 printf("\nget(/%s) = %s\n", _key.c_str(), 593 ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND"); 594 #endif 595 596 return ret; 597 } 598 599 // Returns an object from a Dictionary, identified by it's name. get(const SkPdfNativeObject * key)600 const SkPdfNativeObject* get(const SkPdfNativeObject* key) const { 601 SkPdfMarkObjectUsed(); 602 603 SkASSERT(fObjectType == kDictionary_PdfObjectType); 604 SkASSERT(key->fObjectType == kName_PdfObjectType); 605 606 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) { 607 // TODO(edisonn): report/warn/assert. 608 return NULL; 609 } 610 611 return get(key->fStr.fBuffer, key->fStr.fBytes); 612 } 613 614 // Returns an object from a Dictionary, identified by it's name. get(const char * key)615 const SkPdfNativeObject* get(const char* key) const { 616 SkPdfMarkObjectUsed(); 617 618 return get((const unsigned char*)key, strlen(key)); 619 } 620 621 // Returns an object from a Dictionary, identified by it's name. get(const unsigned char * key,size_t len)622 const SkPdfNativeObject* get(const unsigned char* key, size_t len) const { 623 SkPdfMarkObjectUsed(); 624 625 SkASSERT(fObjectType == kDictionary_PdfObjectType); 626 SkASSERT(key); 627 if (fObjectType != kDictionary_PdfObjectType) { 628 // TODO(edisonn): report/warn/assert. 629 return NULL; 630 } 631 SkPdfNativeObject* ret = NULL; 632 fMap->find((const char*)key, len, &ret); 633 634 #ifdef PDF_TRACE 635 SkString _key; 636 _key.append((const char*)key, len); 637 printf("\nget(/%s) = %s\n", _key.c_str(), 638 ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND"); 639 #endif 640 641 return ret; 642 } 643 644 // Returns an object from a Dictionary, identified by it's name. get(const char * key,const char * abr)645 const SkPdfNativeObject* get(const char* key, const char* abr) const { 646 SkPdfMarkObjectUsed(); 647 648 const SkPdfNativeObject* ret = get(key); 649 // TODO(edisonn): remove || *abr == '\0' and pass NULL in the _autogen files instead. 650 if (ret != NULL || abr == NULL || *abr == '\0') { 651 return ret; 652 } 653 return get(abr); 654 } 655 656 // Returns an object from a Dictionary, identified by it's name. get(const char * key,const char * abr)657 SkPdfNativeObject* get(const char* key, const char* abr) { 658 SkPdfMarkObjectUsed(); 659 660 SkPdfNativeObject* ret = get(key); 661 // TODO(edisonn): remove || *abr == '\0' and pass NULL in the _autogen files instead. 662 if (ret != NULL || abr == NULL || *abr == '\0') { 663 return ret; 664 } 665 return get(abr); 666 } 667 668 // Casts the object to a Dictionary. Asserts if the object is not a Dictionary. asDictionary()669 SkPdfDictionary* asDictionary() { 670 SkPdfMarkObjectUsed(); 671 672 SkASSERT(isDictionary()); 673 if (!isDictionary()) { 674 return NULL; 675 } 676 return (SkPdfDictionary*) this; 677 } 678 679 // Casts the object to a Dictionary. Asserts if the object is not a Dictionary. asDictionary()680 const SkPdfDictionary* asDictionary() const { 681 SkPdfMarkObjectUsed(); 682 683 SkASSERT(isDictionary()); 684 if (!isDictionary()) { 685 return NULL; 686 } 687 return (SkPdfDictionary*) this; 688 } 689 690 691 // Returns true if the object is a Reference. isReference()692 bool isReference() const { 693 SkPdfMarkObjectUsed(); 694 695 return fObjectType == kReference_PdfObjectType; 696 } 697 698 // Returns true if the object is a Boolean. isBoolean()699 bool isBoolean() const { 700 SkPdfMarkObjectUsed(); 701 702 return fObjectType == kBoolean_PdfObjectType; 703 } 704 705 // Returns true if the object is an Integer. isInteger()706 bool isInteger() const { 707 SkPdfMarkObjectUsed(); 708 709 return fObjectType == kInteger_PdfObjectType; 710 } 711 712 private: 713 // Returns true if the object is a Real number. isReal()714 bool isReal() const { 715 SkPdfMarkObjectUsed(); 716 717 return fObjectType == kReal_PdfObjectType; 718 } 719 720 public: 721 // Returns true if the object is a Number (either Integer or Real). isNumber()722 bool isNumber() const { 723 SkPdfMarkObjectUsed(); 724 725 return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_PdfObjectType; 726 } 727 728 // Returns true if the object is a R keyword (used to identify references, e.g. "10 3 R". isKeywordReference()729 bool isKeywordReference() const { 730 SkPdfMarkObjectUsed(); 731 732 return fObjectType == kKeyword_PdfObjectType && fStr.fBytes == 1 && fStr.fBuffer[0] == 'R'; 733 } 734 735 // Returns true if the object is a Keyword. isKeyword()736 bool isKeyword() const { 737 SkPdfMarkObjectUsed(); 738 739 return fObjectType == kKeyword_PdfObjectType; 740 } 741 742 // Returns true if the object is a given Keyword. isKeyword(const char * keyword)743 bool isKeyword(const char* keyword) const { 744 SkPdfMarkObjectUsed(); 745 746 if (!isKeyword()) { 747 return false; 748 } 749 750 if (strlen(keyword) != fStr.fBytes) { 751 return false; 752 } 753 754 if (strncmp(keyword, (const char*)fStr.fBuffer, fStr.fBytes) != 0) { 755 return false; 756 } 757 758 return true; 759 } 760 761 // Returns true if the object is a Name. isName()762 bool isName() const { 763 SkPdfMarkObjectUsed(); 764 765 return fObjectType == kName_PdfObjectType; 766 } 767 768 // Returns true if the object is a given Name. isName(const char * name)769 bool isName(const char* name) const { 770 SkPdfMarkObjectUsed(); 771 772 return fObjectType == kName_PdfObjectType && 773 fStr.fBytes == strlen(name) && 774 strncmp((const char*)fStr.fBuffer, name, fStr.fBytes) == 0; 775 } 776 777 // Returns true if the object is an Array. isArray()778 bool isArray() const { 779 SkPdfMarkObjectUsed(); 780 781 return fObjectType == kArray_PdfObjectType; 782 } 783 784 // Returns true if the object is a Date. 785 // TODO(edisonn): NYI isDate()786 bool isDate() const { 787 SkPdfMarkObjectUsed(); 788 789 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType; 790 } 791 792 // Returns true if the object is a Dictionary. isDictionary()793 bool isDictionary() const { 794 SkPdfMarkObjectUsed(); 795 796 return fObjectType == kDictionary_PdfObjectType; 797 } 798 799 // Returns true if the object is a Date. 800 // TODO(edisonn): NYI isFunction()801 bool isFunction() const { 802 SkPdfMarkObjectUsed(); 803 804 return false; // NYI 805 } 806 807 // Returns true if the object is a Rectangle. isRectangle()808 bool isRectangle() const { 809 SkPdfMarkObjectUsed(); 810 811 // TODO(edisonn): add also that each of these 4 objects are numbers. 812 return fObjectType == kArray_PdfObjectType && fArray->count() == 4; 813 } 814 815 // TODO(edisonn): Design: decide if we should use hasStream or isStream 816 // Returns true if the object has a stream associated with it. hasStream()817 bool hasStream() const { 818 SkPdfMarkObjectUsed(); 819 820 return isDictionary() && fStr.fBuffer != NULL; 821 } 822 823 // Returns the stream associated with the dictionary. As of now, it casts this to Stream. getStream()824 const SkPdfStream* getStream() const { 825 SkPdfMarkObjectUsed(); 826 827 return hasStream() ? (const SkPdfStream*)this : NULL; 828 } 829 830 // Returns the stream associated with the dictionary. As of now, it casts this to Stream. getStream()831 SkPdfStream* getStream() { 832 SkPdfMarkObjectUsed(); 833 834 return hasStream() ? (SkPdfStream*)this : NULL; 835 } 836 837 // Returns true if the object is a String or HexString. isAnyString()838 bool isAnyString() const { 839 SkPdfMarkObjectUsed(); 840 841 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType; 842 } 843 844 // Returns true if the object is a HexString. isHexString()845 bool isHexString() const { 846 SkPdfMarkObjectUsed(); 847 848 return fObjectType == kHexString_PdfObjectType; 849 } 850 851 // Returns true if the object is a Matrix. isMatrix()852 bool isMatrix() const { 853 SkPdfMarkObjectUsed(); 854 855 // TODO(edisonn): add also that each of these 6 objects are numbers. 856 return fObjectType == kArray_PdfObjectType && fArray->count() == 6; 857 } 858 859 // Returns the int value stored in the object. Assert if the object is not an Integer. intValue()860 inline int64_t intValue() const { 861 SkPdfMarkObjectUsed(); 862 863 SkASSERT(fObjectType == kInteger_PdfObjectType); 864 865 if (fObjectType != kInteger_PdfObjectType) { 866 // TODO(edisonn): report/warn/assert. 867 return 0; 868 } 869 return fIntegerValue; 870 } 871 872 private: 873 // Returns the real value stored in the object. Assert if the object is not a Real. realValue()874 inline double realValue() const { 875 SkPdfMarkObjectUsed(); 876 877 SkASSERT(fObjectType == kReal_PdfObjectType); 878 879 if (fObjectType != kReal_PdfObjectType) { 880 // TODO(edisonn): report/warn/assert. 881 return 0; 882 } 883 return fRealValue; 884 } 885 886 public: 887 // Returns the numeric value stored in the object. Assert if the object is not a Real 888 // or an Integer. numberValue()889 inline double numberValue() const { 890 SkPdfMarkObjectUsed(); 891 892 SkASSERT(isNumber()); 893 894 if (!isNumber()) { 895 // TODO(edisonn): report/warn/assert. 896 return 0; 897 } 898 return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue; 899 } 900 901 // Returns the numeric value stored in the object as a scalar. Assert if the object is not 902 // a Realor an Integer. scalarValue()903 inline SkScalar scalarValue() const { 904 SkPdfMarkObjectUsed(); 905 906 SkASSERT(isNumber()); 907 908 if (!isNumber()) { 909 // TODO(edisonn): report/warn/assert. 910 return SkIntToScalar(0); 911 } 912 return fObjectType == kReal_PdfObjectType ? SkDoubleToScalar(fRealValue) : 913 SkIntToScalar(fIntegerValue); 914 } 915 916 // Returns the id of the referenced object. Assert if the object is not a Reference. referenceId()917 int referenceId() const { 918 SkPdfMarkObjectUsed(); 919 920 SkASSERT(fObjectType == kReference_PdfObjectType); 921 return fRef.fId; 922 } 923 924 // Returns the generation of the referenced object. Assert if the object is not a Reference. referenceGeneration()925 int referenceGeneration() const { 926 SkPdfMarkObjectUsed(); 927 928 SkASSERT(fObjectType == kReference_PdfObjectType); 929 return fRef.fGen; 930 } 931 932 // Returns the buffer of a Name object. Assert if the object is not a Name. nameValue()933 inline const char* nameValue() const { 934 SkPdfMarkObjectUsed(); 935 936 SkASSERT(fObjectType == kName_PdfObjectType); 937 938 if (fObjectType != kName_PdfObjectType) { 939 // TODO(edisonn): report/warn/assert. 940 return ""; 941 } 942 return (const char*)fStr.fBuffer; 943 } 944 945 // Returns the buffer of a (Hex)String object. Assert if the object is not a (Hex)String. stringValue()946 inline const char* stringValue() const { 947 SkPdfMarkObjectUsed(); 948 949 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType); 950 951 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) { 952 // TODO(edisonn): report/warn/assert. 953 return ""; 954 } 955 return (const char*)fStr.fBuffer; 956 } 957 958 // Returns the storage of any type that can hold a form of string. strRef()959 inline NotOwnedString strRef() { 960 SkPdfMarkObjectUsed(); 961 962 switch (fObjectType) { 963 case kString_PdfObjectType: 964 case kHexString_PdfObjectType: 965 case kKeyword_PdfObjectType: 966 case kName_PdfObjectType: 967 return fStr; 968 969 default: 970 // TODO(edisonn): report/warning 971 return NotOwnedString(); 972 } 973 } 974 975 // TODO(edisonn): nameValue2 and stringValue2 are used to make code generation easy, 976 // but it is not a performat way to do it, since it will create an extra copy 977 // remove these functions and make code generated faster nameValue2()978 inline SkString nameValue2() const { 979 SkPdfMarkObjectUsed(); 980 981 SkASSERT(fObjectType == kName_PdfObjectType); 982 983 if (fObjectType != kName_PdfObjectType) { 984 // TODO(edisonn): log err 985 return SkString(); 986 } 987 return SkString((const char*)fStr.fBuffer, fStr.fBytes); 988 } 989 990 // Returns an SkString with the value of the (Hex)String object. stringValue2()991 inline SkString stringValue2() const { 992 SkPdfMarkObjectUsed(); 993 994 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType); 995 996 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) { 997 // TODO(edisonn): report/warn/assert. 998 return SkString(); 999 } 1000 return SkString((const char*)fStr.fBuffer, fStr.fBytes); 1001 } 1002 1003 // Returns the boolean of the Bool object. Assert if the object is not a Bool. boolValue()1004 inline bool boolValue() const { 1005 SkPdfMarkObjectUsed(); 1006 1007 SkASSERT(fObjectType == kBoolean_PdfObjectType); 1008 1009 if (fObjectType != kBoolean_PdfObjectType) { 1010 // TODO(edisonn): report/warn/assert. 1011 return false; 1012 } 1013 return fBooleanValue; 1014 } 1015 1016 // Returns the rectangle of the Rectangle object. Assert if the object is not a Rectangle. rectangleValue()1017 SkRect rectangleValue() const { 1018 SkPdfMarkObjectUsed(); 1019 1020 SkASSERT(isRectangle()); 1021 if (!isRectangle()) { 1022 return SkRect::MakeEmpty(); 1023 } 1024 1025 double array[4]; 1026 for (int i = 0; i < 4; i++) { 1027 // TODO(edisonn): version where we could resolve references? 1028 const SkPdfNativeObject* elem = objAtAIndex(i); 1029 if (elem == NULL || !elem->isNumber()) { 1030 // TODO(edisonn): report/warn/assert. 1031 return SkRect::MakeEmpty(); 1032 } 1033 array[i] = elem->numberValue(); 1034 } 1035 1036 return SkRect::MakeLTRB(SkDoubleToScalar(array[0]), 1037 SkDoubleToScalar(array[1]), 1038 SkDoubleToScalar(array[2]), 1039 SkDoubleToScalar(array[3])); 1040 } 1041 1042 // Returns the matrix of the Matrix object. Assert if the object is not a Matrix. matrixValue()1043 SkMatrix matrixValue() const { 1044 SkPdfMarkObjectUsed(); 1045 1046 SkASSERT(isMatrix()); 1047 if (!isMatrix()) { 1048 return SkMatrix::I(); 1049 } 1050 1051 double array[6]; 1052 for (int i = 0; i < 6; i++) { 1053 // TODO(edisonn): version where we could resolve references? 1054 const SkPdfNativeObject* elem = objAtAIndex(i); 1055 if (elem == NULL || !elem->isNumber()) { 1056 // TODO(edisonn): report/warn/assert. 1057 return SkMatrix::I(); 1058 } 1059 array[i] = elem->numberValue(); 1060 } 1061 1062 return SkMatrixFromPdfMatrix(array); 1063 } 1064 1065 // Runs all the filters of this stream, except the last one, if it is a DCT. 1066 // Returns false on failure. 1067 bool filterStream(); 1068 1069 // Runs all the filters of this stream, except the last one, if it is a DCT, a gives back 1070 // the buffer and the length. The object continues to own the buffer. 1071 // Returns false on failure. GetFilteredStreamRef(unsigned char const ** buffer,size_t * len)1072 bool GetFilteredStreamRef(unsigned char const** buffer, size_t* len) { 1073 SkPdfMarkObjectUsed(); 1074 1075 // TODO(edisonn): add params that could let the last filter in place 1076 // if it is jpeg or png to fast load images. 1077 if (!hasStream()) { 1078 return false; 1079 } 1080 1081 filterStream(); 1082 1083 if (buffer) { 1084 *buffer = fStr.fBuffer; 1085 } 1086 1087 if (len) { 1088 *len = fStr.fBytes >> 2; // last 2 bits - TODO(edisonn): clean up. 1089 } 1090 1091 return true; 1092 } 1093 1094 // Returns true if the stream is already filtered. isStreamFiltered()1095 bool isStreamFiltered() const { 1096 SkPdfMarkObjectUsed(); 1097 1098 return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit); 1099 } 1100 1101 // Returns true if this object own the buffer, or false if an Allocator own it. isStreamOwned()1102 bool isStreamOwned() const { 1103 SkPdfMarkObjectUsed(); 1104 1105 return hasStream() && ((fStr.fBytes & 2) == kOwnedStreamBit); 1106 } 1107 1108 // Gives back the original buffer and the length. The object continues to own the buffer. 1109 // Returns false if the stream is already filtered. GetUnfilteredStreamRef(unsigned char const ** buffer,size_t * len)1110 bool GetUnfilteredStreamRef(unsigned char const** buffer, size_t* len) const { 1111 SkPdfMarkObjectUsed(); 1112 1113 if (isStreamFiltered()) { 1114 return false; 1115 } 1116 1117 if (!hasStream()) { 1118 return false; 1119 } 1120 1121 if (buffer) { 1122 *buffer = fStr.fBuffer; 1123 } 1124 1125 if (len) { 1126 *len = fStr.fBytes >> 2; // remove last 2 bits - TODO(edisonn): clean up. 1127 } 1128 1129 return true; 1130 } 1131 1132 // Add a stream to this Dictionarry. Asserts we do not have yet a stream. addStream(const unsigned char * buffer,size_t len)1133 bool addStream(const unsigned char* buffer, size_t len) { 1134 SkPdfMarkObjectUsed(); 1135 1136 SkASSERT(!hasStream()); 1137 SkASSERT(isDictionary()); 1138 1139 if (!isDictionary() || hasStream()) { 1140 return false; 1141 } 1142 1143 fStr.fBuffer = buffer; 1144 fStr.fBytes = (len << 2) + kUnfilteredStreamBit; 1145 1146 return true; 1147 } 1148 appendSpaces(SkString * str,int level)1149 static void appendSpaces(SkString* str, int level) { 1150 for (int i = 0 ; i < level; i++) { 1151 str->append(" "); 1152 } 1153 } 1154 1155 static void append(SkString* str, const char* data, size_t len, const char* prefix = "\\x") { 1156 for (unsigned int i = 0 ; i < len; i++) { 1157 if (data[i] == kNUL_PdfWhiteSpace) { 1158 str->append(prefix); 1159 str->append("00"); 1160 } else if (data[i] == kHT_PdfWhiteSpace) { 1161 str->append(prefix); 1162 str->append("09"); 1163 } else if (data[i] == kLF_PdfWhiteSpace) { 1164 str->append(prefix); 1165 str->append("0A"); 1166 } else if (data[i] == kFF_PdfWhiteSpace) { 1167 str->append(prefix); 1168 str->append("0C"); 1169 } else if (data[i] == kCR_PdfWhiteSpace) { 1170 str->append(prefix); 1171 str->append("0D"); 1172 } else { 1173 str->append(data + i, 1); 1174 } 1175 } 1176 } 1177 1178 // Returns the string representation of the object value. 1179 SkString toString(int firstRowLevel = 0, int level = 0) { 1180 SkString str; 1181 appendSpaces(&str, firstRowLevel); 1182 switch (fObjectType) { 1183 case kInvalid_PdfObjectType: 1184 str.append("__Invalid"); 1185 break; 1186 1187 case kBoolean_PdfObjectType: 1188 str.appendf("%s", fBooleanValue ? "true" : "false"); 1189 break; 1190 1191 case kInteger_PdfObjectType: 1192 str.appendf("%i", (int)fIntegerValue); 1193 break; 1194 1195 case kReal_PdfObjectType: 1196 str.appendf("%f", fRealValue); 1197 break; 1198 1199 case kString_PdfObjectType: 1200 str.append("\""); 1201 append(&str, (const char*)fStr.fBuffer, fStr.fBytes); 1202 str.append("\""); 1203 break; 1204 1205 case kHexString_PdfObjectType: 1206 str.append("<"); 1207 for (unsigned int i = 0 ; i < fStr.fBytes; i++) { 1208 str.appendf("%02x", (unsigned int)fStr.fBuffer[i]); 1209 } 1210 str.append(">"); 1211 break; 1212 1213 case kName_PdfObjectType: 1214 str.append("/"); 1215 append(&str, (const char*)fStr.fBuffer, fStr.fBytes, "#"); 1216 break; 1217 1218 case kKeyword_PdfObjectType: 1219 append(&str, (const char*)fStr.fBuffer, fStr.fBytes); 1220 break; 1221 1222 case kArray_PdfObjectType: 1223 str.append("[\n"); 1224 for (unsigned int i = 0; i < size(); i++) { 1225 str.append(objAtAIndex(i)->toString(level + 1, level + 1)); 1226 if (i < size() - 1) { 1227 str.append(","); 1228 } 1229 str.append("\n"); 1230 } 1231 appendSpaces(&str, level); 1232 str.append("]"); 1233 break; 1234 1235 case kDictionary_PdfObjectType: { 1236 SkTDict<SkPdfNativeObject*>::Iter iter(*fMap); 1237 SkPdfNativeObject* obj = NULL; 1238 const char* key = NULL; 1239 str.append("<<\n"); 1240 while ((key = iter.next(&obj)) != NULL) { 1241 appendSpaces(&str, level + 2); 1242 str.appendf("/%s %s\n", key, 1243 obj->toString(0, level + (int) strlen(key) + 4).c_str()); 1244 } 1245 appendSpaces(&str, level); 1246 str.append(">>"); 1247 if (hasStream()) { 1248 const unsigned char* stream = NULL; 1249 size_t length = 0; 1250 if (GetFilteredStreamRef(&stream, &length)) { 1251 str.append("stream\n"); 1252 append(&str, (const char*)stream, length > 256 ? 256 : length); 1253 str.append("\nendstream"); 1254 } else { 1255 str.append("stream STREAM_ERROR endstream"); 1256 } 1257 } 1258 } 1259 break; 1260 1261 case kNull_PdfObjectType: 1262 str = "NULL"; 1263 break; 1264 1265 case kReference_PdfObjectType: 1266 str.appendf("%i %i R", fRef.fId, fRef.fGen); 1267 break; 1268 1269 case kUndefined_PdfObjectType: 1270 str = "Undefined"; 1271 break; 1272 1273 default: 1274 str = "Error"; 1275 break; 1276 } 1277 1278 return str; 1279 } 1280 1281 private: makeStringCore(const unsigned char * start,SkPdfNativeObject * obj,ObjectType type)1282 static void makeStringCore(const unsigned char* start, SkPdfNativeObject* obj, 1283 ObjectType type) { 1284 makeStringCore(start, strlen((const char*)start), obj, type); 1285 } 1286 makeStringCore(const unsigned char * start,const unsigned char * end,SkPdfNativeObject * obj,ObjectType type)1287 static void makeStringCore(const unsigned char* start, const unsigned char* end, 1288 SkPdfNativeObject* obj, ObjectType type) { 1289 makeStringCore(start, end - start, obj, type); 1290 } 1291 makeStringCore(const unsigned char * start,size_t bytes,SkPdfNativeObject * obj,ObjectType type)1292 static void makeStringCore(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj, 1293 ObjectType type) { 1294 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 1295 1296 obj->fObjectType = type; 1297 obj->fStr.fBuffer = start; 1298 obj->fStr.fBytes = bytes; 1299 } 1300 1301 bool applyFilter(const char* name); 1302 bool applyFlateDecodeFilter(); 1303 bool applyDCTDecodeFilter(); 1304 }; 1305 1306 // These classes are provided for convenience. You still have to make sure an SkPdfInteger 1307 // is indeed an Integer. 1308 class SkPdfStream : public SkPdfNativeObject {}; 1309 class SkPdfArray : public SkPdfNativeObject {}; 1310 class SkPdfString : public SkPdfNativeObject {}; 1311 class SkPdfHexString : public SkPdfNativeObject {}; 1312 class SkPdfInteger : public SkPdfNativeObject {}; 1313 class SkPdfReal : public SkPdfNativeObject {}; 1314 class SkPdfNumber : public SkPdfNativeObject {}; 1315 1316 class SkPdfName : public SkPdfNativeObject { SkPdfName()1317 SkPdfName() : SkPdfNativeObject() { 1318 SkPdfNativeObject::makeName((const unsigned char*)"", this); 1319 } 1320 public: SkPdfName(char * name)1321 SkPdfName(char* name) : SkPdfNativeObject() { 1322 this->makeName((const unsigned char*)name, this); 1323 } 1324 }; 1325 1326 #endif // SkPdfNativeObject 1327