| 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 #define kOwnedStreamBit 2 | |
| 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 enum DataType { | |
| 53 kEmpty_Data, | |
| 54 kFont_Data, | |
| 55 kBitmap_Data, | |
| 56 }; | |
| 57 | |
| 58 private: | |
| 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 e
rrors | |
| 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, o
therwise, 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 | |
| 91 public: | |
| 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* ob
j) { | |
| 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_PdfObject
Type); | |
| 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_PdfObj
ectType); | |
| 279 } | |
| 280 | |
| 281 static void makeHexString(const unsigned char* start, const unsigned char* e
nd, SkPdfObject* obj) { | |
| 282 makeStringCore(start, end - start, obj, kHexString_PdfObjectType); | |
| 283 } | |
| 284 | |
| 285 static void makeHexString(const unsigned char* start, size_t bytes, SkPdfObj
ect* 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_PdfObjectTy
pe); | |
| 292 } | |
| 293 | |
| 294 static void makeName(const unsigned char* start, const unsigned char* end, S
kPdfObject* 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_PdfObjec
tType); | |
| 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, SkPdfObjec
t* obj) { | |
| 312 makeStringCore(start, bytes, obj, kKeyword_PdfObjectType); | |
| 313 } | |
| 314 | |
| 315 | |
| 316 | |
| 317 // TODO(edisonn): make the functions to return SkPdfArray, move these functi
ons 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 f
unctions 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 f
unction | |
| 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/has
h | |
| 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 != kDictionar
y_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 != kDictionar
y_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 != kDictionar
y_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 } | |
| 547 private: | |
| 548 bool isReal() const { | |
| 549 return fObjectType == kReal_PdfObjectType; | |
| 550 } | |
| 551 public: | |
| 552 bool isNumber() const { | |
| 553 return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_Pdf
ObjectType; | |
| 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; // N
YI + 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; // N
YI + 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 } | |
| 643 private: | |
| 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 } | |
| 653 public: | |
| 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 == kHexStri
ng_PdfObjectType); | |
| 697 | |
| 698 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_Pd
fObjectType) { | |
| 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 generati
on easy, | |
| 720 // but it is not a performat way to do it, since it will create an extra cop
y | |
| 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 == kHexStri
ng_PdfObjectType); | |
| 734 | |
| 735 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_Pd
fObjectType) { | |
| 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 + st
rlen(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 | |
| 966 private: | |
| 967 static void makeStringCore(const unsigned char* start, SkPdfObject* obj, Obj
ectType 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, SkPdfOb
ject* 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 | |
| 988 class SkPdfStream : public SkPdfObject {}; | |
| 989 class SkPdfArray : public SkPdfObject {}; | |
| 990 class SkPdfString : public SkPdfObject {}; | |
| 991 class SkPdfHexString : public SkPdfObject {}; | |
| 992 class SkPdfInteger : public SkPdfObject {}; | |
| 993 class SkPdfReal : public SkPdfObject {}; | |
| 994 class SkPdfNumber : public SkPdfObject {}; | |
| 995 | |
| 996 class SkPdfName : public SkPdfObject { | |
| 997 SkPdfName() : SkPdfObject() { | |
| 998 SkPdfObject::makeName((const unsigned char*)"", this); | |
| 999 } | |
| 1000 public: | |
| 1001 SkPdfName(char* name) : SkPdfObject() { | |
| 1002 this->makeName((const unsigned char*)name, this); | |
| 1003 } | |
| 1004 }; | |
| 1005 | |
| 1006 #endif // EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFOBJECT_H_ | |
| OLD | NEW |