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