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