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