Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(442)

Side by Side Diff: experimental/PdfViewer/pdfparser/native/SkPdfObject.h

Issue 23020003: pdfviewer: debug code for drawText (show magenta background for text, to show text even when we fai… (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698