blob: d496670bc1d5577c6e745cc10af40d42014bd62c [file] [log] [blame]
edisonn@google.com571c70b2013-07-10 17:09:50 +00001#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
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 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 errors
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, otherwise, 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
87public:
88
edisonn@google.com222382b2013-07-10 22:33:10 +000089 SkPdfObject() : fObjectType(kInvalid_PdfObjectType), fMap(NULL), fData(NULL) {}
edisonn@google.com571c70b2013-07-10 17:09:50 +000090
91 inline void* data() {
92 return fData;
93 }
94
95 inline void setData(void* data) {
96 fData = data;
97 }
98
edisonn@google.com222382b2013-07-10 22:33:10 +000099// ~SkPdfObject() {
100// //reset(); must be called manually!
101// }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000102
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, 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 (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(unsigned char* start, SkPdfObject* obj) {
245 makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType);
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_PdfObjectType);
259 }
260
261 static void makeHexString(unsigned char* start, unsigned char* end, SkPdfObject* obj) {
262 makeStringCore(start, end - start, obj, kHexString_PdfObjectType);
263 }
264
265 static void makeHexString(unsigned char* start, size_t bytes, SkPdfObject* obj) {
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_PdfObjectType);
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_PdfObjectType);
285 }
286
287 static void makeKeyword(unsigned char* start, unsigned char* end, SkPdfObject* 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 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(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
edisonn@google.comd761e322013-07-22 17:29:43 +0000387 return set(key->fStr.fBuffer, key->fStr.fBytes, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000388 }
389
390 bool set(const char* key, SkPdfObject* value) {
edisonn@google.comd761e322013-07-22 17:29:43 +0000391 return set((const unsigned char*)key, strlen(key), value);
392 }
393
394 bool set(const unsigned char* key, size_t len, SkPdfObject* value) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000395 SkASSERT(fObjectType == kDictionary_PdfObjectType);
396
397 if (fObjectType != kDictionary_PdfObjectType) {
398 // TODO(edisonn): report err
399 return false;
400 }
401
edisonn@google.comd761e322013-07-22 17:29:43 +0000402 return fMap->set((const char*)key, len, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000403 }
404
405 SkPdfObject* get(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
edisonn@google.com3fc48262013-07-22 15:29:55 +0000411 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000412 }
413
414 SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
415
edisonn@google.comd761e322013-07-22 17:29:43 +0000416 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000417 }
418
419 SkPdfObject* get(const char* key) {
edisonn@google.comd761e322013-07-22 17:29:43 +0000420 return get((const unsigned char*)key, strlen(key));
421 }
422
423 SkPdfObject* get(const unsigned char* key, size_t len) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000424 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;
edisonn@google.comd761e322013-07-22 17:29:43 +0000431 fMap->find((const char*)key, len, &ret);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000432 return ret;
433 }
434
435 const SkPdfObject* get(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
edisonn@google.com3fc48262013-07-22 15:29:55 +0000441 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000442 }
443
444 SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
445
edisonn@google.comd761e322013-07-22 17:29:43 +0000446 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000447 }
448
edisonn@google.com571c70b2013-07-10 17:09:50 +0000449 const SkPdfObject* get(const char* key) const {
edisonn@google.comd761e322013-07-22 17:29:43 +0000450 return get((const unsigned char*)key, strlen(key));
451 }
452
453 const SkPdfObject* get(const unsigned char* key, size_t len) const {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000454 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;
edisonn@google.comd761e322013-07-22 17:29:43 +0000461 fMap->find((const char*)key, len, &ret);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000462 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
edisonn@google.com78b38b12013-07-15 18:20:58 +0000534 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
edisonn@google.com571c70b2013-07-10 17:09:50 +0000538 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 int referenceId() const {
611 SkASSERT(fObjectType == kReference_PdfObjectType);
612 return fRef.fId;
613 }
614
615 int referenceGeneration() const {
616 SkASSERT(fObjectType == kReference_PdfObjectType);
617 return fRef.fGen;
618 }
619
620 inline const char* nameValue() const {
621 SkASSERT(fObjectType == kName_PdfObjectType);
622
623 if (fObjectType != kName_PdfObjectType) {
624 // TODO(edisonn): log err
625 return "";
626 }
627 return (const char*)fStr.fBuffer;
628 }
629
630 inline const char* stringValue() const {
631 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
632
633 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
634 // TODO(edisonn): log err
635 return "";
636 }
637 return (const char*)fStr.fBuffer;
638 }
639
640 // TODO(edisonn): nameValue2 and stringValue2 are used to make code generation easy,
641 // but it is not a performat way to do it, since it will create an extra copy
642 // remove these functions and make code generated faster
643 inline std::string nameValue2() const {
644 SkASSERT(fObjectType == kName_PdfObjectType);
645
646 if (fObjectType != kName_PdfObjectType) {
647 // TODO(edisonn): log err
648 return "";
649 }
650 return (const char*)fStr.fBuffer;
651 }
652
653 inline std::string stringValue2() const {
654 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
655
656 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
657 // TODO(edisonn): log err
658 return "";
659 }
660 return (const char*)fStr.fBuffer;
661 }
662
663 inline bool boolValue() const {
664 SkASSERT(fObjectType == kBoolean_PdfObjectType);
665
666 if (fObjectType == kBoolean_PdfObjectType) {
667 // TODO(edisonn): log err
668 return false;
669 }
670 return fBooleanValue;
671 }
672
673 SkRect rectangleValue() const {
674 SkASSERT(isRectangle());
675 if (!isRectangle()) {
676 return SkRect::MakeEmpty();
677 }
678
679 double array[4];
680 for (int i = 0; i < 4; i++) {
681 // TODO(edisonn): version where we could resolve references?
682 const SkPdfObject* elem = objAtAIndex(i);
683 if (elem == NULL || !elem->isNumber()) {
684 // TODO(edisonn): report error
685 return SkRect::MakeEmpty();
686 }
687 array[i] = elem->numberValue();
688 }
689
690 return SkRect::MakeLTRB(SkDoubleToScalar(array[0]),
691 SkDoubleToScalar(array[1]),
692 SkDoubleToScalar(array[2]),
693 SkDoubleToScalar(array[3]));
694 }
695
696 SkMatrix matrixValue() const {
697 SkASSERT(isMatrix());
698 if (!isMatrix()) {
699 return SkMatrix::I();
700 }
701
702 double array[6];
703 for (int i = 0; i < 6; i++) {
704 // TODO(edisonn): version where we could resolve references?
705 const SkPdfObject* elem = objAtAIndex(i);
706 if (elem == NULL || !elem->isNumber()) {
707 // TODO(edisonn): report error
708 return SkMatrix::I();
709 }
710 array[i] = elem->numberValue();
711 }
712
713 return SkMatrixFromPdfMatrix(array);
714 }
715
716 bool filterStream(SkPdfAllocator* allocator);
717
718
719 bool GetFilteredStreamRef(unsigned char** buffer, size_t* len, SkPdfAllocator* allocator) {
720 // TODO(edisonn): add params that couls let the last filter in place if it is jpeg or png to fast load images
721 if (!hasStream()) {
722 return false;
723 }
724
725 filterStream(allocator);
726
727 if (buffer) {
728 *buffer = fStr.fBuffer;
729 }
730
731 if (len) {
732 *len = fStr.fBytes >> 1; // last bit
733 }
734
735 return true;
736 }
737
738 bool isStreamFiltered() const {
739 return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit);
740 }
741
742 bool GetUnfilteredStreamRef(unsigned char** buffer, size_t* len) const {
743 if (isStreamFiltered()) {
744 return false;
745 }
746
747 if (!hasStream()) {
748 return false;
749 }
750
751 if (buffer) {
752 *buffer = fStr.fBuffer;
753 }
754
755 if (len) {
756 *len = fStr.fBytes >> 1; // remove slast bit
757 }
758
759 return true;
760 }
761
762 bool addStream(unsigned char* buffer, size_t len) {
763 SkASSERT(!hasStream());
764 SkASSERT(isDictionary());
765
766 if (!isDictionary() || hasStream()) {
767 return false;
768 }
769
770 fStr.fBuffer = buffer;
771 fStr.fBytes = (len << 2) + kUnfilteredStreamBit;
772
773 return true;
774 }
775
776 SkString toString() {
777 SkString str;
778 switch (fObjectType) {
779 case kInvalid_PdfObjectType:
780 str.append("Invalid");
781 break;
782
783 case kBoolean_PdfObjectType:
784 str.appendf("Boolean: %s", fBooleanValue ? "true" : "false");
785 break;
786
787 case kInteger_PdfObjectType:
788 str.appendf("Integer: %i", (int)fIntegerValue);
789 break;
790
791 case kReal_PdfObjectType:
792 str.appendf("Real: %f", fRealValue);
793 break;
794
795 case kString_PdfObjectType:
796 str.appendf("String, len() = %u: ", (unsigned int)fStr.fBytes);
797 str.append((const char*)fStr.fBuffer, fStr.fBytes);
798 break;
799
800 case kHexString_PdfObjectType:
801 str.appendf("HexString, len() = %u: ", (unsigned int)fStr.fBytes);
802 str.append((const char*)fStr.fBuffer, fStr.fBytes);
803 break;
804
805 case kName_PdfObjectType:
806 str.appendf("Name, len() = %u: ", (unsigned int)fStr.fBytes);
807 str.append((const char*)fStr.fBuffer, fStr.fBytes);
808 break;
809
810 case kKeyword_PdfObjectType:
811 str.appendf("Keyword, len() = %u: ", (unsigned int)fStr.fBytes);
812 str.append((const char*)fStr.fBuffer, fStr.fBytes);
813 break;
814
815 case kArray_PdfObjectType:
816 str.append("Array, size() = %i [", size());
817 for (unsigned int i = 0; i < size(); i++) {
818 str.append(objAtAIndex(i)->toString());
819 }
820 str.append("]");
821 break;
822
823 case kDictionary_PdfObjectType:
824 // TODO(edisonn): NYI
825 str.append("Dictionary: NYI");
826 if (hasStream()) {
827 str.append(" HAS_STREAM");
828 }
829 break;
830
831 case kNull_PdfObjectType:
832 str = "NULL";
833 break;
834
835 case kReference_PdfObjectType:
836 str.appendf("Reference: %i %i", fRef.fId, fRef.fGen);
837 break;
838
839 case kUndefined_PdfObjectType:
840 str = "Undefined";
841 break;
842
843 default:
844 str = "Internal Error Object Type";
845 break;
846 }
847
848 return str;
849 }
850
851private:
852 static void makeStringCore(unsigned char* start, SkPdfObject* obj, ObjectType type) {
853 makeStringCore(start, strlen((const char*)start), obj, type);
854 }
855
856 static void makeStringCore(unsigned char* start, unsigned char* end, SkPdfObject* obj, ObjectType type) {
857 makeStringCore(start, end - start, obj, type);
858 }
859
860 static void makeStringCore(unsigned char* start, size_t bytes, SkPdfObject* obj, ObjectType type) {
861 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
862
863 obj->fObjectType = type;
864 obj->fStr.fBuffer = start;
865 obj->fStr.fBytes = bytes;
866 }
867
868 bool applyFilter(const char* name, SkPdfAllocator* allocator);
869 bool applyFlateDecodeFilter(SkPdfAllocator* allocator);
870 bool applyDCTDecodeFilter(SkPdfAllocator* allocator);
871};
872
873class SkPdfStream : public SkPdfObject {};
874class SkPdfArray : public SkPdfObject {};
875class SkPdfString : public SkPdfObject {};
876class SkPdfHexString : public SkPdfObject {};
877class SkPdfInteger : public SkPdfObject {};
878class SkPdfReal : public SkPdfObject {};
879class SkPdfNumber : public SkPdfObject {};
880
edisonn@google.com78b38b12013-07-15 18:20:58 +0000881class SkPdfName : public SkPdfObject {
882 SkPdfName() : SkPdfObject() {
883 SkPdfObject::makeName((unsigned char*)"", this);
884 }
885public:
886 SkPdfName(char* name) : SkPdfObject() {
887 this->makeName((unsigned char*)name, this);
888 }
889};
890
edisonn@google.com571c70b2013-07-10 17:09:50 +0000891#endif // EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFOBJECT_H_