SkPdfNativeObject.h revision 3fc482620e8af9442f588e3bf364e198c41ba913
1#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFOBJECT_H_ 2#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFOBJECT_H_ 3 4#include <stdint.h> 5#include <string.h> 6#include <string> 7#include "SkTDArray.h" 8#include "SkTDict.h" 9#include "SkRect.h" 10#include "SkMatrix.h" 11#include "SkString.h" 12 13#include "SkPdfNYI.h" 14#include "SkPdfConfig.h" 15 16class SkPdfDictionary; 17class SkPdfStream; 18class SkPdfAllocator; 19 20// TODO(edisonn): macro it and move it to utils 21SkMatrix SkMatrixFromPdfMatrix(double array[6]); 22 23 24#define kFilteredStreamBit 0 25#define kUnfilteredStreamBit 1 26 27 28class SkPdfObject { 29 public: 30 enum ObjectType { 31 kInvalid_PdfObjectType, 32 33 kBoolean_PdfObjectType, 34 kInteger_PdfObjectType, 35 kReal_PdfObjectType, 36 kString_PdfObjectType, 37 kHexString_PdfObjectType, 38 kName_PdfObjectType, 39 kKeyword_PdfObjectType, 40 //kStream_PdfObjectType, // attached to a Dictionary 41 kArray_PdfObjectType, 42 kDictionary_PdfObjectType, 43 kNull_PdfObjectType, 44 45 // TODO(edisonn): after the pdf has been loaded completely, resolve all references 46 // try the same thing with delayed loaded ... 47 kReference_PdfObjectType, 48 49 kUndefined_PdfObjectType, // per 1.4 spec, if the same key appear twice in the dictionary, the value is undefined 50 }; 51 52private: 53 struct NotOwnedString { 54 unsigned char* fBuffer; 55 size_t fBytes; 56 }; 57 58 struct Reference { 59 unsigned int fId; 60 unsigned int fGen; 61 }; 62 63 // TODO(edisonn): add stream start, stream end, where stream is weither the file 64 // or decoded/filtered pdf stream 65 66 // TODO(edisonn): add warning/report per object 67 // TODO(edisonn): add flag fUsed, to be used once the parsing is complete, 68 // so we could show what parts have been proccessed, ignored, or generated errors 69 70 ObjectType fObjectType; 71 72 union { 73 bool fBooleanValue; 74 int64_t fIntegerValue; 75 // TODO(edisonn): double, float? typedefed 76 double fRealValue; 77 NotOwnedString fStr; 78 79 // TODO(edisonn): make sure the foorprint of fArray and fMap is small, otherwise, use pointers, or classes with up to 8 bytes in footprint 80 SkTDArray<SkPdfObject*>* fArray; 81 Reference fRef; 82 }; 83 SkTDict<SkPdfObject*>* fMap; 84 void* fData; 85 86 87public: 88 89 SkPdfObject() : fObjectType(kInvalid_PdfObjectType), fMap(NULL), fData(NULL) {} 90 91 inline void* data() { 92 return fData; 93 } 94 95 inline void setData(void* data) { 96 fData = data; 97 } 98 99// ~SkPdfObject() { 100// //reset(); must be called manually! 101// } 102 103 void reset() { 104 switch (fObjectType) { 105 case kArray_PdfObjectType: 106 delete fArray; 107 break; 108 109 case kDictionary_PdfObjectType: 110 delete fMap; 111 break; 112 113 default: 114 break; 115 } 116 fObjectType = kInvalid_PdfObjectType; 117 } 118 119 ObjectType type() { return fObjectType; } 120 121 const char* c_str() const { 122 switch (fObjectType) { 123 case kString_PdfObjectType: 124 case kHexString_PdfObjectType: 125 case kKeyword_PdfObjectType: 126 return (const char*)fStr.fBuffer; 127 128 default: 129 // TODO(edisonn): report/warning 130 return NULL; 131 } 132 } 133 134 size_t len() const { 135 switch (fObjectType) { 136 case kString_PdfObjectType: 137 case kHexString_PdfObjectType: 138 case kKeyword_PdfObjectType: 139 return fStr.fBytes; 140 141 default: 142 // TODO(edisonn): report/warning 143 return 0; 144 } 145 } 146 147 148 // TODO(edisonn): NYI 149 SkPdfDate& dateValue() const { 150 static SkPdfDate nyi; 151 return nyi; 152 } 153 154 // TODO(edisonn): NYI 155 SkPdfFunction& functionValue() const { 156 static SkPdfFunction nyi; 157 return nyi; 158 } 159 160 // TODO(edisonn): NYI 161 SkPdfFileSpec& fileSpecValue() const { 162 static SkPdfFileSpec nyi; 163 return nyi; 164 } 165 166 // TODO(edisonn): NYI 167 SkPdfTree& treeValue() const { 168 static SkPdfTree nyi; 169 return nyi; 170 } 171 172 173 static void makeBoolean(bool value, SkPdfObject* obj) { 174 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 175 176 obj->fObjectType = kBoolean_PdfObjectType; 177 obj->fBooleanValue = value; 178 } 179 180 static SkPdfObject makeBoolean(bool value) { 181 SkPdfObject obj; 182 obj.fObjectType = kBoolean_PdfObjectType; 183 obj.fBooleanValue = value; 184 return obj; 185 } 186 187 static void makeInteger(int64_t value, SkPdfObject* obj) { 188 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 189 190 obj->fObjectType = kInteger_PdfObjectType; 191 obj->fIntegerValue = value; 192 } 193 194 static void makeReal(double value, SkPdfObject* obj) { 195 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 196 197 obj->fObjectType = kReal_PdfObjectType; 198 obj->fRealValue = value; 199 } 200 201 static void makeNull(SkPdfObject* obj) { 202 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 203 204 obj->fObjectType = kNull_PdfObjectType; 205 } 206 207 static SkPdfObject makeNull() { 208 SkPdfObject obj; 209 obj.fObjectType = kNull_PdfObjectType; 210 return obj; 211 } 212 213 static SkPdfObject kNull; 214 215 static void makeNumeric(unsigned char* start, unsigned char* end, SkPdfObject* obj) { 216 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 217 218 // TODO(edisonn): NYI properly 219 // if has dot (impl), or exceeds max int, is real, otherwise is int 220 bool isInt = true; 221 for (unsigned char* current = start; current < end; current++) { 222 if (*current == '.') { 223 isInt = false; 224 break; 225 } 226 // TODO(edisonn): report parse issue with numbers like "24asdasd123" 227 } 228 if (isInt) { 229 makeInteger(atol((const char*)start), obj); 230 } else { 231 makeReal(atof((const char*)start), obj); 232 } 233 } 234 235 static void makeReference(unsigned int id, unsigned int gen, SkPdfObject* obj) { 236 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 237 238 obj->fObjectType = kReference_PdfObjectType; 239 obj->fRef.fId = id; 240 obj->fRef.fGen = gen; 241 } 242 243 244 static void makeString(unsigned char* start, SkPdfObject* obj) { 245 makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType); 246 } 247 248 static void makeString(unsigned char* start, unsigned char* end, SkPdfObject* obj) { 249 makeStringCore(start, end - start, obj, kString_PdfObjectType); 250 } 251 252 static void makeString(unsigned char* start, size_t bytes, SkPdfObject* obj) { 253 makeStringCore(start, bytes, obj, kString_PdfObjectType); 254 } 255 256 257 static void makeHexString(unsigned char* start, SkPdfObject* obj) { 258 makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType); 259 } 260 261 static void makeHexString(unsigned char* start, unsigned char* end, SkPdfObject* obj) { 262 makeStringCore(start, end - start, obj, kHexString_PdfObjectType); 263 } 264 265 static void makeHexString(unsigned char* start, size_t bytes, SkPdfObject* obj) { 266 makeStringCore(start, bytes, obj, kHexString_PdfObjectType); 267 } 268 269 270 static void makeName(unsigned char* start, SkPdfObject* obj) { 271 makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType); 272 } 273 274 static void makeName(unsigned char* start, unsigned char* end, SkPdfObject* obj) { 275 makeStringCore(start, end - start, obj, kName_PdfObjectType); 276 } 277 278 static void makeName(unsigned char* start, size_t bytes, SkPdfObject* obj) { 279 makeStringCore(start, bytes, obj, kName_PdfObjectType); 280 } 281 282 283 static void makeKeyword(unsigned char* start, SkPdfObject* obj) { 284 makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType); 285 } 286 287 static void makeKeyword(unsigned char* start, unsigned char* end, SkPdfObject* obj) { 288 makeStringCore(start, end - start, obj, kKeyword_PdfObjectType); 289 } 290 291 static void makeKeyword(unsigned char* start, size_t bytes, SkPdfObject* obj) { 292 makeStringCore(start, bytes, obj, kKeyword_PdfObjectType); 293 } 294 295 296 297 // TODO(edisonn): make the functions to return SkPdfArray, move these functions in SkPdfArray 298 static void makeEmptyArray(SkPdfObject* obj) { 299 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 300 301 obj->fObjectType = kArray_PdfObjectType; 302 obj->fArray = new SkTDArray<SkPdfObject*>(); 303 // return (SkPdfArray*)obj; 304 } 305 306 bool appendInArray(SkPdfObject* obj) { 307 SkASSERT(fObjectType == kArray_PdfObjectType); 308 if (fObjectType != kArray_PdfObjectType) { 309 // TODO(edisonn): report err 310 return false; 311 } 312 313 fArray->push(obj); 314 return true; 315 } 316 317 size_t size() const { 318 SkASSERT(fObjectType == kArray_PdfObjectType); 319 320 return fArray->count(); 321 } 322 323 SkPdfObject* objAtAIndex(int i) { 324 SkASSERT(fObjectType == kArray_PdfObjectType); 325 326 return (*fArray)[i]; 327 } 328 329 SkPdfObject* removeLastInArray() { 330 SkASSERT(fObjectType == kArray_PdfObjectType); 331 332 SkPdfObject* ret = NULL; 333 fArray->pop(&ret); 334 335 return ret; 336 } 337 338 339 const SkPdfObject* objAtAIndex(int i) const { 340 SkASSERT(fObjectType == kArray_PdfObjectType); 341 342 return (*fArray)[i]; 343 } 344 345 SkPdfObject* operator[](int i) { 346 SkASSERT(fObjectType == kArray_PdfObjectType); 347 348 return (*fArray)[i]; 349 } 350 351 const SkPdfObject* operator[](int i) const { 352 SkASSERT(fObjectType == kArray_PdfObjectType); 353 354 return (*fArray)[i]; 355 } 356 357 358 // TODO(edisonn): make the functions to return SkPdfDictionary, move these functions in SkPdfDictionary 359 static void makeEmptyDictionary(SkPdfObject* obj) { 360 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 361 362 obj->fObjectType = kDictionary_PdfObjectType; 363 obj->fMap = new SkTDict<SkPdfObject*>(1); 364 obj->fStr.fBuffer = NULL; 365 obj->fStr.fBytes = 0; 366 } 367 368 // TODO(edisonn): get all the possible names from spec, and compute a hash function 369 // that would create no overlaps in the same dictionary 370 // or build a tree of chars that when followed goes to a unique id/index/hash 371 // TODO(edisonn): generate constants like kDictFoo, kNameDict_name 372 // which will be used in code 373 // add function SkPdfFastNameKey key(const char* key); 374 // TODO(edisonn): setting the same key twike, will make the value undefined! 375 bool set(SkPdfObject* key, SkPdfObject* value) { 376 SkASSERT(fObjectType == kDictionary_PdfObjectType); 377 SkASSERT(key->fObjectType == kName_PdfObjectType); 378 379 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) { 380 // TODO(edisonn): report err 381 return false; 382 } 383 384 // we rewrite all delimiters and white spaces with '\0', so we expect the end of name to be '\0' 385 SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0'); 386 387 return set((char*)key->fStr.fBuffer, value); 388 } 389 390 bool set(const char* key, SkPdfObject* value) { 391 SkASSERT(fObjectType == kDictionary_PdfObjectType); 392 393 if (fObjectType != kDictionary_PdfObjectType) { 394 // TODO(edisonn): report err 395 return false; 396 } 397 398 return fMap->set(key, value); 399 } 400 401 SkPdfObject* get(SkPdfObject* key) { 402 SkASSERT(fObjectType == kDictionary_PdfObjectType); 403 SkASSERT(key->fObjectType == kName_PdfObjectType); 404 405 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) { 406 // TODO(edisonn): report err 407 return NULL; 408 } 409 410 SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0'); 411 412 return get((char*)key->fStr.fBuffer); 413 } 414 415 SkPdfObject* get(const char* key) { 416 SkASSERT(fObjectType == kDictionary_PdfObjectType); 417 SkASSERT(key); 418 if (fObjectType != kDictionary_PdfObjectType) { 419 // TODO(edisonn): report err 420 return NULL; 421 } 422 SkPdfObject* ret = NULL; 423 fMap->find(key, &ret); 424 return ret; 425 } 426 427 const SkPdfObject* get(SkPdfObject* key) const { 428 SkASSERT(fObjectType == kDictionary_PdfObjectType); 429 SkASSERT(key->fObjectType == kName_PdfObjectType); 430 431 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) { 432 // TODO(edisonn): report err 433 return NULL; 434 } 435 436 SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0'); 437 438 return get((char*)key->fStr.fBuffer); 439 } 440 441 442 const SkPdfObject* get(const char* key) const { 443 SkASSERT(fObjectType == kDictionary_PdfObjectType); 444 SkASSERT(key); 445 if (fObjectType != kDictionary_PdfObjectType) { 446 // TODO(edisonn): report err 447 return NULL; 448 } 449 SkPdfObject* ret = NULL; 450 fMap->find(key, &ret); 451 return ret; 452 } 453 454 const SkPdfObject* get(const char* key, const char* abr) const { 455 const SkPdfObject* ret = get(key); 456 // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL 457 // make this distiontion in generator, and remove "" from condition 458 if (ret != NULL || abr == NULL || *abr == '\0') { 459 return ret; 460 } 461 return get(abr); 462 } 463 464 SkPdfObject* get(const char* key, const char* abr) { 465 SkPdfObject* ret = get(key); 466 // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL 467 // make this distiontion in generator, and remove "" from condition 468 if (ret != NULL || abr == NULL || *abr == '\0') { 469 return ret; 470 } 471 return get(abr); 472 } 473 474 SkPdfDictionary* asDictionary() { 475 SkASSERT(isDictionary()); 476 if (!isDictionary()) { 477 return NULL; 478 } 479 return (SkPdfDictionary*) this; 480 } 481 482 const SkPdfDictionary* asDictionary() const { 483 SkASSERT(isDictionary()); 484 if (!isDictionary()) { 485 return NULL; 486 } 487 return (SkPdfDictionary*) this; 488 } 489 490 491 bool isReference() const { 492 return fObjectType == kReference_PdfObjectType; 493 } 494 495 bool isBoolean() const { 496 return fObjectType == kBoolean_PdfObjectType; 497 } 498 499 bool isInteger() const { 500 return fObjectType == kInteger_PdfObjectType; 501 } 502private: 503 bool isReal() const { 504 return fObjectType == kReal_PdfObjectType; 505 } 506public: 507 bool isNumber() const { 508 return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_PdfObjectType; 509 } 510 511 bool isKeywordReference() const { 512 return fObjectType == kKeyword_PdfObjectType && fStr.fBytes == 1 && fStr.fBuffer[0] == 'R'; 513 } 514 515 bool isKeyword() const { 516 return fObjectType == kKeyword_PdfObjectType; 517 } 518 519 bool isName() const { 520 return fObjectType == kName_PdfObjectType; 521 } 522 523 bool isName(const char* name) const { 524 return fObjectType == kName_PdfObjectType && fStr.fBytes == strlen(name) && strncmp((const char*)fStr.fBuffer, name, fStr.fBytes) == 0; 525 } 526 527 bool isArray() const { 528 return fObjectType == kArray_PdfObjectType; 529 } 530 531 bool isDate() const { 532 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType; 533 } 534 535 bool isDictionary() const { 536 return fObjectType == kDictionary_PdfObjectType; 537 } 538 539 bool isFunction() const { 540 return false; // NYI 541 } 542 543 bool isRectangle() const { 544 return fObjectType == kArray_PdfObjectType && fArray->count() == 4; // NYI + and elems are numbers 545 } 546 547 // TODO(edisonn): has stream .. or is stream ... TBD 548 bool hasStream() const { 549 return isDictionary() && fStr.fBuffer != NULL; 550 } 551 552 // TODO(edisonn): has stream .. or is stream ... TBD 553 const SkPdfStream* getStream() const { 554 return hasStream() ? (const SkPdfStream*)this : NULL; 555 } 556 557 SkPdfStream* getStream() { 558 return hasStream() ? (SkPdfStream*)this : NULL; 559 } 560 561 bool isAnyString() const { 562 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType; 563 } 564 565 bool isMatrix() const { 566 return fObjectType == kArray_PdfObjectType && fArray->count() == 6; // NYI + and elems are numbers 567 } 568 569 inline int64_t intValue() const { 570 SkASSERT(fObjectType == kInteger_PdfObjectType); 571 572 if (fObjectType != kInteger_PdfObjectType) { 573 // TODO(edisonn): log err 574 return 0; 575 } 576 return fIntegerValue; 577 } 578private: 579 inline double realValue() const { 580 SkASSERT(fObjectType == kReal_PdfObjectType); 581 582 if (fObjectType != kReal_PdfObjectType) { 583 // TODO(edisonn): log err 584 return 0; 585 } 586 return fRealValue; 587 } 588public: 589 inline double numberValue() const { 590 SkASSERT(isNumber()); 591 592 if (!isNumber()) { 593 // TODO(edisonn): log err 594 return 0; 595 } 596 return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue; 597 } 598 599 int referenceId() const { 600 SkASSERT(fObjectType == kReference_PdfObjectType); 601 return fRef.fId; 602 } 603 604 int referenceGeneration() const { 605 SkASSERT(fObjectType == kReference_PdfObjectType); 606 return fRef.fGen; 607 } 608 609 inline const char* nameValue() const { 610 SkASSERT(fObjectType == kName_PdfObjectType); 611 612 if (fObjectType != kName_PdfObjectType) { 613 // TODO(edisonn): log err 614 return ""; 615 } 616 return (const char*)fStr.fBuffer; 617 } 618 619 inline const char* stringValue() const { 620 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType); 621 622 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) { 623 // TODO(edisonn): log err 624 return ""; 625 } 626 return (const char*)fStr.fBuffer; 627 } 628 629 // TODO(edisonn): nameValue2 and stringValue2 are used to make code generation easy, 630 // but it is not a performat way to do it, since it will create an extra copy 631 // remove these functions and make code generated faster 632 inline std::string nameValue2() const { 633 SkASSERT(fObjectType == kName_PdfObjectType); 634 635 if (fObjectType != kName_PdfObjectType) { 636 // TODO(edisonn): log err 637 return ""; 638 } 639 return (const char*)fStr.fBuffer; 640 } 641 642 inline std::string stringValue2() const { 643 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType); 644 645 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) { 646 // TODO(edisonn): log err 647 return ""; 648 } 649 return (const char*)fStr.fBuffer; 650 } 651 652 inline bool boolValue() const { 653 SkASSERT(fObjectType == kBoolean_PdfObjectType); 654 655 if (fObjectType == kBoolean_PdfObjectType) { 656 // TODO(edisonn): log err 657 return false; 658 } 659 return fBooleanValue; 660 } 661 662 SkRect rectangleValue() const { 663 SkASSERT(isRectangle()); 664 if (!isRectangle()) { 665 return SkRect::MakeEmpty(); 666 } 667 668 double array[4]; 669 for (int i = 0; i < 4; i++) { 670 // TODO(edisonn): version where we could resolve references? 671 const SkPdfObject* elem = objAtAIndex(i); 672 if (elem == NULL || !elem->isNumber()) { 673 // TODO(edisonn): report error 674 return SkRect::MakeEmpty(); 675 } 676 array[i] = elem->numberValue(); 677 } 678 679 return SkRect::MakeLTRB(SkDoubleToScalar(array[0]), 680 SkDoubleToScalar(array[1]), 681 SkDoubleToScalar(array[2]), 682 SkDoubleToScalar(array[3])); 683 } 684 685 SkMatrix matrixValue() const { 686 SkASSERT(isMatrix()); 687 if (!isMatrix()) { 688 return SkMatrix::I(); 689 } 690 691 double array[6]; 692 for (int i = 0; i < 6; i++) { 693 // TODO(edisonn): version where we could resolve references? 694 const SkPdfObject* elem = objAtAIndex(i); 695 if (elem == NULL || !elem->isNumber()) { 696 // TODO(edisonn): report error 697 return SkMatrix::I(); 698 } 699 array[i] = elem->numberValue(); 700 } 701 702 return SkMatrixFromPdfMatrix(array); 703 } 704 705 bool filterStream(SkPdfAllocator* allocator); 706 707 708 bool GetFilteredStreamRef(unsigned char** buffer, size_t* len, SkPdfAllocator* allocator) { 709 // TODO(edisonn): add params that couls let the last filter in place if it is jpeg or png to fast load images 710 if (!hasStream()) { 711 return false; 712 } 713 714 filterStream(allocator); 715 716 if (buffer) { 717 *buffer = fStr.fBuffer; 718 } 719 720 if (len) { 721 *len = fStr.fBytes >> 1; // last bit 722 } 723 724 return true; 725 } 726 727 bool isStreamFiltered() const { 728 return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit); 729 } 730 731 bool GetUnfilteredStreamRef(unsigned char** buffer, size_t* len) const { 732 if (isStreamFiltered()) { 733 return false; 734 } 735 736 if (!hasStream()) { 737 return false; 738 } 739 740 if (buffer) { 741 *buffer = fStr.fBuffer; 742 } 743 744 if (len) { 745 *len = fStr.fBytes >> 1; // remove slast bit 746 } 747 748 return true; 749 } 750 751 bool addStream(unsigned char* buffer, size_t len) { 752 SkASSERT(!hasStream()); 753 SkASSERT(isDictionary()); 754 755 if (!isDictionary() || hasStream()) { 756 return false; 757 } 758 759 fStr.fBuffer = buffer; 760 fStr.fBytes = (len << 2) + kUnfilteredStreamBit; 761 762 return true; 763 } 764 765 SkString toString() { 766 SkString str; 767 switch (fObjectType) { 768 case kInvalid_PdfObjectType: 769 str.append("Invalid"); 770 break; 771 772 case kBoolean_PdfObjectType: 773 str.appendf("Boolean: %s", fBooleanValue ? "true" : "false"); 774 break; 775 776 case kInteger_PdfObjectType: 777 str.appendf("Integer: %i", (int)fIntegerValue); 778 break; 779 780 case kReal_PdfObjectType: 781 str.appendf("Real: %f", fRealValue); 782 break; 783 784 case kString_PdfObjectType: 785 str.appendf("String, len() = %u: ", (unsigned int)fStr.fBytes); 786 str.append((const char*)fStr.fBuffer, fStr.fBytes); 787 break; 788 789 case kHexString_PdfObjectType: 790 str.appendf("HexString, len() = %u: ", (unsigned int)fStr.fBytes); 791 str.append((const char*)fStr.fBuffer, fStr.fBytes); 792 break; 793 794 case kName_PdfObjectType: 795 str.appendf("Name, len() = %u: ", (unsigned int)fStr.fBytes); 796 str.append((const char*)fStr.fBuffer, fStr.fBytes); 797 break; 798 799 case kKeyword_PdfObjectType: 800 str.appendf("Keyword, len() = %u: ", (unsigned int)fStr.fBytes); 801 str.append((const char*)fStr.fBuffer, fStr.fBytes); 802 break; 803 804 case kArray_PdfObjectType: 805 str.append("Array, size() = %i [", size()); 806 for (unsigned int i = 0; i < size(); i++) { 807 str.append(objAtAIndex(i)->toString()); 808 } 809 str.append("]"); 810 break; 811 812 case kDictionary_PdfObjectType: 813 // TODO(edisonn): NYI 814 str.append("Dictionary: NYI"); 815 if (hasStream()) { 816 str.append(" HAS_STREAM"); 817 } 818 break; 819 820 case kNull_PdfObjectType: 821 str = "NULL"; 822 break; 823 824 case kReference_PdfObjectType: 825 str.appendf("Reference: %i %i", fRef.fId, fRef.fGen); 826 break; 827 828 case kUndefined_PdfObjectType: 829 str = "Undefined"; 830 break; 831 832 default: 833 str = "Internal Error Object Type"; 834 break; 835 } 836 837 return str; 838 } 839 840private: 841 static void makeStringCore(unsigned char* start, SkPdfObject* obj, ObjectType type) { 842 makeStringCore(start, strlen((const char*)start), obj, type); 843 } 844 845 static void makeStringCore(unsigned char* start, unsigned char* end, SkPdfObject* obj, ObjectType type) { 846 makeStringCore(start, end - start, obj, type); 847 } 848 849 static void makeStringCore(unsigned char* start, size_t bytes, SkPdfObject* obj, ObjectType type) { 850 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 851 852 obj->fObjectType = type; 853 obj->fStr.fBuffer = start; 854 obj->fStr.fBytes = bytes; 855 } 856 857 bool applyFilter(const char* name, SkPdfAllocator* allocator); 858 bool applyFlateDecodeFilter(SkPdfAllocator* allocator); 859 bool applyDCTDecodeFilter(SkPdfAllocator* allocator); 860}; 861 862class SkPdfStream : public SkPdfObject {}; 863class SkPdfArray : public SkPdfObject {}; 864class SkPdfString : public SkPdfObject {}; 865class SkPdfHexString : public SkPdfObject {}; 866class SkPdfInteger : public SkPdfObject {}; 867class SkPdfReal : public SkPdfObject {}; 868class SkPdfNumber : public SkPdfObject {}; 869 870class SkPdfName : public SkPdfObject { 871 SkPdfName() : SkPdfObject() { 872 SkPdfObject::makeName((unsigned char*)"", this); 873 } 874public: 875 SkPdfName(char* name) : SkPdfObject() { 876 this->makeName((unsigned char*)name, this); 877 } 878}; 879 880#endif // EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFOBJECT_H_ 881