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