SkPdfNativeObject.h revision a0cefa18fc25cca4264be04ce30c0c9692487a02
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 52private: 53 struct Reference { 54 unsigned int fId; 55 unsigned int fGen; 56 }; 57 58 // TODO(edisonn): add stream start, stream end, where stream is weither the file 59 // or decoded/filtered pdf stream 60 61 // TODO(edisonn): add warning/report per object 62 // TODO(edisonn): add flag fUsed, to be used once the parsing is complete, 63 // so we could show what parts have been proccessed, ignored, or generated errors 64 65 ObjectType fObjectType; 66 67 union { 68 bool fBooleanValue; 69 int64_t fIntegerValue; 70 // TODO(edisonn): double, float? typedefed 71 double fRealValue; 72 NotOwnedString fStr; 73 74 // TODO(edisonn): make sure the foorprint of fArray and fMap is small, otherwise, use pointers, or classes with up to 8 bytes in footprint 75 SkTDArray<SkPdfObject*>* fArray; 76 Reference fRef; 77 }; 78 SkTDict<SkPdfObject*>* fMap; 79 void* fData; 80 81 82public: 83 84 SkPdfObject() : fObjectType(kInvalid_PdfObjectType), fMap(NULL), fData(NULL) {} 85 86 inline void* data() { 87 return fData; 88 } 89 90 inline void setData(void* data) { 91 fData = data; 92 } 93 94// ~SkPdfObject() { 95// //reset(); must be called manually! 96// } 97 98 void reset() { 99 switch (fObjectType) { 100 case kArray_PdfObjectType: 101 delete fArray; 102 break; 103 104 case kDictionary_PdfObjectType: 105 delete fMap; 106 if (isStreamOwned()) { 107 delete[] fStr.fBuffer; 108 fStr.fBuffer = NULL; 109 fStr.fBytes = 0; 110 } 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(const unsigned char* start, const 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 (const 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(const unsigned char* start, SkPdfObject* obj) { 245 makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType); 246 } 247 248 static void makeString(const unsigned char* start, const unsigned char* end, SkPdfObject* obj) { 249 makeStringCore(start, end - start, obj, kString_PdfObjectType); 250 } 251 252 static void makeString(const unsigned char* start, size_t bytes, SkPdfObject* obj) { 253 makeStringCore(start, bytes, obj, kString_PdfObjectType); 254 } 255 256 257 static void makeHexString(const unsigned char* start, SkPdfObject* obj) { 258 makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType); 259 } 260 261 static void makeHexString(const unsigned char* start, const unsigned char* end, SkPdfObject* obj) { 262 makeStringCore(start, end - start, obj, kHexString_PdfObjectType); 263 } 264 265 static void makeHexString(const unsigned char* start, size_t bytes, SkPdfObject* obj) { 266 makeStringCore(start, bytes, obj, kHexString_PdfObjectType); 267 } 268 269 270 static void makeName(const unsigned char* start, SkPdfObject* obj) { 271 makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType); 272 } 273 274 static void makeName(const unsigned char* start, const unsigned char* end, SkPdfObject* obj) { 275 makeStringCore(start, end - start, obj, kName_PdfObjectType); 276 } 277 278 static void makeName(const unsigned char* start, size_t bytes, SkPdfObject* obj) { 279 makeStringCore(start, bytes, obj, kName_PdfObjectType); 280 } 281 282 283 static void makeKeyword(const unsigned char* start, SkPdfObject* obj) { 284 makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType); 285 } 286 287 static void makeKeyword(const unsigned char* start, const unsigned char* end, SkPdfObject* obj) { 288 makeStringCore(start, end - start, obj, kKeyword_PdfObjectType); 289 } 290 291 static void makeKeyword(const 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(const 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(key->fStr.fBuffer, key->fStr.fBytes, value); 388 } 389 390 bool set(const char* key, SkPdfObject* value) { 391 return set((const unsigned char*)key, strlen(key), value); 392 } 393 394 bool set(const unsigned char* key, size_t len, SkPdfObject* value) { 395 SkASSERT(fObjectType == kDictionary_PdfObjectType); 396 397 if (fObjectType != kDictionary_PdfObjectType) { 398 // TODO(edisonn): report err 399 return false; 400 } 401 402 return fMap->set((const char*)key, len, value); 403 } 404 405 SkPdfObject* get(const SkPdfObject* key) { 406 SkASSERT(fObjectType == kDictionary_PdfObjectType); 407 SkASSERT(key->fObjectType == kName_PdfObjectType); 408 409 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) { 410 // TODO(edisonn): report err 411 return NULL; 412 } 413 414 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0'); 415 416 return get(key->fStr.fBuffer, key->fStr.fBytes); 417 } 418 419 SkPdfObject* get(const char* key) { 420 return get((const unsigned char*)key, strlen(key)); 421 } 422 423 SkPdfObject* get(const unsigned char* key, size_t len) { 424 SkASSERT(fObjectType == kDictionary_PdfObjectType); 425 SkASSERT(key); 426 if (fObjectType != kDictionary_PdfObjectType) { 427 // TODO(edisonn): report err 428 return NULL; 429 } 430 SkPdfObject* ret = NULL; 431 fMap->find((const char*)key, len, &ret); 432 return ret; 433 } 434 435 const SkPdfObject* get(const SkPdfObject* key) const { 436 SkASSERT(fObjectType == kDictionary_PdfObjectType); 437 SkASSERT(key->fObjectType == kName_PdfObjectType); 438 439 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) { 440 // TODO(edisonn): report err 441 return NULL; 442 } 443 444 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0'); 445 446 return get(key->fStr.fBuffer, key->fStr.fBytes); 447 } 448 449 const SkPdfObject* get(const char* key) const { 450 return get((const unsigned char*)key, strlen(key)); 451 } 452 453 const SkPdfObject* get(const unsigned char* key, size_t len) const { 454 SkASSERT(fObjectType == kDictionary_PdfObjectType); 455 SkASSERT(key); 456 if (fObjectType != kDictionary_PdfObjectType) { 457 // TODO(edisonn): report err 458 return NULL; 459 } 460 SkPdfObject* ret = NULL; 461 fMap->find((const char*)key, len, &ret); 462 return ret; 463 } 464 465 const SkPdfObject* get(const char* key, const char* abr) const { 466 const SkPdfObject* ret = get(key); 467 // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL 468 // make this distiontion in generator, and remove "" from condition 469 if (ret != NULL || abr == NULL || *abr == '\0') { 470 return ret; 471 } 472 return get(abr); 473 } 474 475 SkPdfObject* get(const char* key, const char* abr) { 476 SkPdfObject* ret = get(key); 477 // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL 478 // make this distiontion in generator, and remove "" from condition 479 if (ret != NULL || abr == NULL || *abr == '\0') { 480 return ret; 481 } 482 return get(abr); 483 } 484 485 SkPdfDictionary* asDictionary() { 486 SkASSERT(isDictionary()); 487 if (!isDictionary()) { 488 return NULL; 489 } 490 return (SkPdfDictionary*) this; 491 } 492 493 const SkPdfDictionary* asDictionary() const { 494 SkASSERT(isDictionary()); 495 if (!isDictionary()) { 496 return NULL; 497 } 498 return (SkPdfDictionary*) this; 499 } 500 501 502 bool isReference() const { 503 return fObjectType == kReference_PdfObjectType; 504 } 505 506 bool isBoolean() const { 507 return fObjectType == kBoolean_PdfObjectType; 508 } 509 510 bool isInteger() const { 511 return fObjectType == kInteger_PdfObjectType; 512 } 513private: 514 bool isReal() const { 515 return fObjectType == kReal_PdfObjectType; 516 } 517public: 518 bool isNumber() const { 519 return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_PdfObjectType; 520 } 521 522 bool isKeywordReference() const { 523 return fObjectType == kKeyword_PdfObjectType && fStr.fBytes == 1 && fStr.fBuffer[0] == 'R'; 524 } 525 526 bool isKeyword() const { 527 return fObjectType == kKeyword_PdfObjectType; 528 } 529 530 bool isName() const { 531 return fObjectType == kName_PdfObjectType; 532 } 533 534 bool isName(const char* name) const { 535 return fObjectType == kName_PdfObjectType && fStr.fBytes == strlen(name) && strncmp((const char*)fStr.fBuffer, name, fStr.fBytes) == 0; 536 } 537 538 bool isArray() const { 539 return fObjectType == kArray_PdfObjectType; 540 } 541 542 bool isDate() const { 543 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType; 544 } 545 546 bool isDictionary() const { 547 return fObjectType == kDictionary_PdfObjectType; 548 } 549 550 bool isFunction() const { 551 return false; // NYI 552 } 553 554 bool isRectangle() const { 555 return fObjectType == kArray_PdfObjectType && fArray->count() == 4; // NYI + and elems are numbers 556 } 557 558 // TODO(edisonn): has stream .. or is stream ... TBD 559 bool hasStream() const { 560 return isDictionary() && fStr.fBuffer != NULL; 561 } 562 563 // TODO(edisonn): has stream .. or is stream ... TBD 564 const SkPdfStream* getStream() const { 565 return hasStream() ? (const SkPdfStream*)this : NULL; 566 } 567 568 SkPdfStream* getStream() { 569 return hasStream() ? (SkPdfStream*)this : NULL; 570 } 571 572 bool isAnyString() const { 573 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType; 574 } 575 576 bool isMatrix() const { 577 return fObjectType == kArray_PdfObjectType && fArray->count() == 6; // NYI + and elems are numbers 578 } 579 580 inline int64_t intValue() const { 581 SkASSERT(fObjectType == kInteger_PdfObjectType); 582 583 if (fObjectType != kInteger_PdfObjectType) { 584 // TODO(edisonn): log err 585 return 0; 586 } 587 return fIntegerValue; 588 } 589private: 590 inline double realValue() const { 591 SkASSERT(fObjectType == kReal_PdfObjectType); 592 593 if (fObjectType != kReal_PdfObjectType) { 594 // TODO(edisonn): log err 595 return 0; 596 } 597 return fRealValue; 598 } 599public: 600 inline double numberValue() const { 601 SkASSERT(isNumber()); 602 603 if (!isNumber()) { 604 // TODO(edisonn): log err 605 return 0; 606 } 607 return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue; 608 } 609 610 inline SkScalar scalarValue() const { 611 SkASSERT(isNumber()); 612 613 if (!isNumber()) { 614 // TODO(edisonn): log err 615 return SkIntToScalar(0); 616 } 617 return fObjectType == kReal_PdfObjectType ? SkDoubleToScalar(fRealValue) : 618 SkIntToScalar(fIntegerValue); 619 } 620 621 int referenceId() const { 622 SkASSERT(fObjectType == kReference_PdfObjectType); 623 return fRef.fId; 624 } 625 626 int referenceGeneration() const { 627 SkASSERT(fObjectType == kReference_PdfObjectType); 628 return fRef.fGen; 629 } 630 631 inline const char* nameValue() const { 632 SkASSERT(fObjectType == kName_PdfObjectType); 633 634 if (fObjectType != kName_PdfObjectType) { 635 // TODO(edisonn): log err 636 return ""; 637 } 638 return (const char*)fStr.fBuffer; 639 } 640 641 inline const char* stringValue() const { 642 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType); 643 644 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) { 645 // TODO(edisonn): log err 646 return ""; 647 } 648 return (const char*)fStr.fBuffer; 649 } 650 651 inline NotOwnedString strRef() { 652 switch (fObjectType) { 653 case kString_PdfObjectType: 654 case kHexString_PdfObjectType: 655 case kKeyword_PdfObjectType: 656 return fStr; 657 658 default: 659 // TODO(edisonn): report/warning 660 return NotOwnedString(); 661 } 662 } 663 664 // TODO(edisonn): nameValue2 and stringValue2 are used to make code generation easy, 665 // but it is not a performat way to do it, since it will create an extra copy 666 // remove these functions and make code generated faster 667 inline std::string nameValue2() const { 668 SkASSERT(fObjectType == kName_PdfObjectType); 669 670 if (fObjectType != kName_PdfObjectType) { 671 // TODO(edisonn): log err 672 return ""; 673 } 674 return std::string((const char*)fStr.fBuffer, fStr.fBytes); 675 } 676 677 inline std::string stringValue2() const { 678 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType); 679 680 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) { 681 // TODO(edisonn): log err 682 return ""; 683 } 684 return std::string((const char*)fStr.fBuffer, fStr.fBytes); 685 } 686 687 inline bool boolValue() const { 688 SkASSERT(fObjectType == kBoolean_PdfObjectType); 689 690 if (fObjectType == kBoolean_PdfObjectType) { 691 // TODO(edisonn): log err 692 return false; 693 } 694 return fBooleanValue; 695 } 696 697 SkRect rectangleValue() const { 698 SkASSERT(isRectangle()); 699 if (!isRectangle()) { 700 return SkRect::MakeEmpty(); 701 } 702 703 double array[4]; 704 for (int i = 0; i < 4; i++) { 705 // TODO(edisonn): version where we could resolve references? 706 const SkPdfObject* elem = objAtAIndex(i); 707 if (elem == NULL || !elem->isNumber()) { 708 // TODO(edisonn): report error 709 return SkRect::MakeEmpty(); 710 } 711 array[i] = elem->numberValue(); 712 } 713 714 return SkRect::MakeLTRB(SkDoubleToScalar(array[0]), 715 SkDoubleToScalar(array[1]), 716 SkDoubleToScalar(array[2]), 717 SkDoubleToScalar(array[3])); 718 } 719 720 SkMatrix matrixValue() const { 721 SkASSERT(isMatrix()); 722 if (!isMatrix()) { 723 return SkMatrix::I(); 724 } 725 726 double array[6]; 727 for (int i = 0; i < 6; i++) { 728 // TODO(edisonn): version where we could resolve references? 729 const SkPdfObject* elem = objAtAIndex(i); 730 if (elem == NULL || !elem->isNumber()) { 731 // TODO(edisonn): report error 732 return SkMatrix::I(); 733 } 734 array[i] = elem->numberValue(); 735 } 736 737 return SkMatrixFromPdfMatrix(array); 738 } 739 740 bool filterStream(); 741 742 743 bool GetFilteredStreamRef(unsigned char const** buffer, size_t* len) { 744 // TODO(edisonn): add params that couls let the last filter in place if it is jpeg or png to fast load images 745 if (!hasStream()) { 746 return false; 747 } 748 749 filterStream(); 750 751 if (buffer) { 752 *buffer = fStr.fBuffer; 753 } 754 755 if (len) { 756 *len = fStr.fBytes >> 2; // last 2 bits 757 } 758 759 return true; 760 } 761 762 bool isStreamFiltered() const { 763 return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit); 764 } 765 766 bool isStreamOwned() const { 767 return hasStream() && ((fStr.fBytes & 2) == kOwnedStreamBit); 768 } 769 770 bool GetUnfilteredStreamRef(unsigned char const** buffer, size_t* len) const { 771 if (isStreamFiltered()) { 772 return false; 773 } 774 775 if (!hasStream()) { 776 return false; 777 } 778 779 if (buffer) { 780 *buffer = fStr.fBuffer; 781 } 782 783 if (len) { 784 *len = fStr.fBytes >> 2; // remove last 2 bits 785 } 786 787 return true; 788 } 789 790 bool addStream(const unsigned char* buffer, size_t len) { 791 SkASSERT(!hasStream()); 792 SkASSERT(isDictionary()); 793 794 if (!isDictionary() || hasStream()) { 795 return false; 796 } 797 798 fStr.fBuffer = buffer; 799 fStr.fBytes = (len << 2) + kUnfilteredStreamBit; 800 801 return true; 802 } 803 804 SkString toString() { 805 SkString str; 806 switch (fObjectType) { 807 case kInvalid_PdfObjectType: 808 str.append("Invalid"); 809 break; 810 811 case kBoolean_PdfObjectType: 812 str.appendf("Boolean: %s", fBooleanValue ? "true" : "false"); 813 break; 814 815 case kInteger_PdfObjectType: 816 str.appendf("Integer: %i", (int)fIntegerValue); 817 break; 818 819 case kReal_PdfObjectType: 820 str.appendf("Real: %f", fRealValue); 821 break; 822 823 case kString_PdfObjectType: 824 str.appendf("String, len() = %u: ", (unsigned int)fStr.fBytes); 825 str.append((const char*)fStr.fBuffer, fStr.fBytes); 826 break; 827 828 case kHexString_PdfObjectType: 829 str.appendf("HexString, len() = %u: ", (unsigned int)fStr.fBytes); 830 str.append((const char*)fStr.fBuffer, fStr.fBytes); 831 break; 832 833 case kName_PdfObjectType: 834 str.appendf("Name, len() = %u: ", (unsigned int)fStr.fBytes); 835 str.append((const char*)fStr.fBuffer, fStr.fBytes); 836 break; 837 838 case kKeyword_PdfObjectType: 839 str.appendf("Keyword, len() = %u: ", (unsigned int)fStr.fBytes); 840 str.append((const char*)fStr.fBuffer, fStr.fBytes); 841 break; 842 843 case kArray_PdfObjectType: 844 str.append("Array, size() = %i [", size()); 845 for (unsigned int i = 0; i < size(); i++) { 846 str.append(objAtAIndex(i)->toString()); 847 } 848 str.append("]"); 849 break; 850 851 case kDictionary_PdfObjectType: 852 // TODO(edisonn): NYI 853 str.append("Dictionary: NYI"); 854 if (hasStream()) { 855 str.append(" HAS_STREAM"); 856 } 857 break; 858 859 case kNull_PdfObjectType: 860 str = "NULL"; 861 break; 862 863 case kReference_PdfObjectType: 864 str.appendf("Reference: %i %i", fRef.fId, fRef.fGen); 865 break; 866 867 case kUndefined_PdfObjectType: 868 str = "Undefined"; 869 break; 870 871 default: 872 str = "Internal Error Object Type"; 873 break; 874 } 875 876 return str; 877 } 878 879private: 880 static void makeStringCore(const unsigned char* start, SkPdfObject* obj, ObjectType type) { 881 makeStringCore(start, strlen((const char*)start), obj, type); 882 } 883 884 static void makeStringCore(const unsigned char* start, const unsigned char* end, SkPdfObject* obj, ObjectType type) { 885 makeStringCore(start, end - start, obj, type); 886 } 887 888 static void makeStringCore(const unsigned char* start, size_t bytes, SkPdfObject* obj, ObjectType type) { 889 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 890 891 obj->fObjectType = type; 892 obj->fStr.fBuffer = start; 893 obj->fStr.fBytes = bytes; 894 } 895 896 bool applyFilter(const char* name); 897 bool applyFlateDecodeFilter(); 898 bool applyDCTDecodeFilter(); 899}; 900 901class SkPdfStream : public SkPdfObject {}; 902class SkPdfArray : public SkPdfObject {}; 903class SkPdfString : public SkPdfObject {}; 904class SkPdfHexString : public SkPdfObject {}; 905class SkPdfInteger : public SkPdfObject {}; 906class SkPdfReal : public SkPdfObject {}; 907class SkPdfNumber : public SkPdfObject {}; 908 909class SkPdfName : public SkPdfObject { 910 SkPdfName() : SkPdfObject() { 911 SkPdfObject::makeName((const unsigned char*)"", this); 912 } 913public: 914 SkPdfName(char* name) : SkPdfObject() { 915 this->makeName((const unsigned char*)name, this); 916 } 917}; 918 919#endif // EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFOBJECT_H_ 920