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

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

Issue 1266093003: Remove experimental/PdfViewer (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2015-08-03 (Monday) 10:43:56 EDT Created 5 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
OLDNEW
(Empty)
1 /*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #ifndef SkPdfNativeObject_DEFINED
9 #define SkPdfNativeObject_DEFINED
10
11 #include <stdint.h>
12 #include <string.h>
13
14 #include "SkMatrix.h"
15 #include "SkPdfConfig.h"
16 #include "SkPdfNativeTokenizer.h"
17 #include "SkPdfNYI.h"
18 #include "SkPdfUtils.h"
19 #include "SkRect.h"
20 #include "SkString.h"
21 #include "SkTDArray.h"
22 #include "SkTDict.h"
23
24 class SkPdfDictionary;
25 class SkPdfStream;
26 class SkPdfAllocator;
27
28 // TODO(edisonn): remove these constants and clean up the code.
29 #define kFilteredStreamBit 0
30 #define kUnfilteredStreamBit 1
31 #define kOwnedStreamBit 2
32
33 /** \class SkPdfNativeObject
34 *
35 * The SkPdfNativeObject class is used to store a pdf object. Classes that inhe rit it are not
36 * allowed to add fields.
37 *
38 * SkPdfAllocator will allocate them in chunks and will free them in destructor .
39 *
40 * You can allocate one on the stack, as long as you call reset() at the end, a nd any objects it
41 * points to in an allocator. But if your object is a simple one, like number, then
42 * putting it on stack will be just fine.
43 *
44 */
45 class SkPdfNativeObject {
46 public:
47 enum ObjectType {
48 // The type will have only one of these values, but for error reporting , we make it an enum
49 // so it can easily report that something was expected to be one of a f ew types
50 kInvalid_PdfObjectType = 1 << 1,
51
52 kBoolean_PdfObjectType = 1 << 2,
53 kInteger_PdfObjectType = 1 << 3,
54 kReal_PdfObjectType = 1 << 4,
55 _kNumber_PdfObjectType = kInteger_PdfObjectType | kReal_PdfObjectType,
56 kString_PdfObjectType = 1 << 5,
57 kHexString_PdfObjectType = 1 << 6,
58 _kAnyString_PdfObjectType = kString_PdfObjectType | kHexString_PdfObjec tType,
59 kName_PdfObjectType = 1 << 7,
60 kKeyword_PdfObjectType = 1 << 8,
61 _kStream_PdfObjectType = 1 << 9, // attached to a Dictionary, do not use
62 kArray_PdfObjectType = 1 << 10,
63 kDictionary_PdfObjectType = 1 << 11,
64 kNull_PdfObjectType = 1 << 12,
65
66 kReference_PdfObjectType = 1 << 13,
67
68 kUndefined_PdfObjectType = 1 << 14, // per 1.4 spec, if the same key a ppear twice in the
69 // dictionary, the value is undefi ned.
70
71 _kObject_PdfObjectType = -1,
72 };
73
74 enum DataType {
75 kEmpty_Data,
76 kFont_Data,
77 kBitmap_Data,
78 };
79
80 private:
81 // TODO(edisonn): assert reset operations while in rendering! The objects sh ould be reset
82 // only when rendering is completed.
83 uint32_t fInRendering : 1;
84 uint32_t fUnused : 31;
85
86 struct Reference {
87 unsigned int fId;
88 unsigned int fGen;
89 };
90
91 ObjectType fObjectType;
92
93 union {
94 bool fBooleanValue;
95 int64_t fIntegerValue;
96 // TODO(edisonn): double, float, SkScalar?
97 double fRealValue;
98 NotOwnedString fStr;
99
100 SkTDArray<SkPdfNativeObject*>* fArray;
101 Reference fRef;
102 };
103 SkTDict<SkPdfNativeObject*>* fMap;
104
105 // TODO(edisonn): rename data with cache
106 void* fData;
107 DataType fDataType;
108
109 #ifdef PDF_TRACK_OBJECT_USAGE
110 // Records if the object was used during rendering/proccessing. It can be us ed to track
111 // what features are only partially implemented, by looking at what objects have not been
112 // accessed.
113 mutable bool fUsed;
114 #endif // PDF_TRACK_OBJECT_USAGE
115
116 #ifdef PDF_TRACK_STREAM_OFFSETS
117 public:
118 // TODO(edisonn): replace them with char* start, end - and a mechanism to re gister streams.
119 int fStreamId;
120 int fOffsetStart;
121 int fOffsetEnd;
122 #endif // PDF_TRACK_STREAM_OFFSETS
123
124 public:
125
126 #ifdef PDF_TRACK_STREAM_OFFSETS
127 // TODO(edisonn): remove these ones.
128 int streamId() const { return fStreamId; }
129 int offsetStart() const { return fOffsetStart; }
130 int offsetEnd() const { return fOffsetEnd; }
131 #endif // PDF_TRACK_STREAM_OFFSETS
132
133 SkPdfNativeObject() : fInRendering(0)
134 , fObjectType(kInvalid_PdfObjectType)
135 , fMap(NULL)
136 , fData(NULL)
137 , fDataType(kEmpty_Data)
138 #ifdef PDF_TRACK_OBJECT_USAGE
139 , fUsed(false)
140 #endif // PDF_TRACK_OBJECT_USAGE
141
142 #ifdef PDF_TRACK_STREAM_OFFSETS
143 , fStreamId(-1)
144 , fOffsetStart(-1)
145 , fOffsetEnd(-1)
146 #endif // PDF_TRACK_STREAM_OFFSETS
147 {}
148
149 // Used to verify if a form is used in rendering, to check for infinite loop s.
150 bool inRendering() const { return fInRendering != 0; }
151 void startRendering() {fInRendering = 1;}
152 void doneRendering() {fInRendering = 0;}
153
154 // Each object can cache one entry associated with it.
155 // for example a SkPdfImage could cache an SkBitmap, of a SkPdfFont, could c ache a SkTypeface.
156 inline bool hasData(DataType type) {
157 return type == fDataType;
158 }
159
160 // returns the cached value
161 inline void* data(DataType type) {
162 return type == fDataType ? fData : NULL;
163 }
164
165 // Stores something in the cache
166 inline void setData(void* data, DataType type) {
167 releaseData();
168 fDataType = type;
169 fData = data;
170 }
171
172 // destroys the cache
173 void releaseData();
174
175 // TODO(edisonn): add an assert that reset was called
176 // ~SkPdfNativeObject() {
177 // //reset(); must be called manually! Normally, will be called by alloc ator destructor.
178 // }
179
180 // Resets a pdf object, deleting all resources directly referenced.
181 // It will not reset/delete indirect resources.
182 // (e.g. it deletes only the array holding pointers to objects, but does not del the objects)
183 void reset() {
184 SkPdfMarkObjectUnused();
185
186 switch (fObjectType) {
187 case kArray_PdfObjectType:
188 delete fArray;
189 break;
190
191 case kDictionary_PdfObjectType:
192 delete fMap;
193 if (isStreamOwned()) {
194 delete[] fStr.fBuffer;
195 fStr.fBuffer = NULL;
196 fStr.fBytes = 0;
197 }
198 break;
199
200 default:
201 break;
202 }
203 fObjectType = kInvalid_PdfObjectType;
204 releaseData();
205 }
206
207 // returns the object type (Null, Integer, String, Dictionary, ... )
208 // It does not specify what type of dictionary we have.
209 ObjectType type() {
210 SkPdfMarkObjectUsed();
211
212 return fObjectType;
213 }
214
215 // Gives quick access to the buffer's address of a string/keyword/name
216 const char* c_str() const {
217 SkPdfMarkObjectUsed();
218
219 switch (fObjectType) {
220 case kString_PdfObjectType:
221 case kHexString_PdfObjectType:
222 case kKeyword_PdfObjectType:
223 case kName_PdfObjectType:
224 return (const char*)fStr.fBuffer;
225
226 default:
227 // TODO(edisonn): report/warning/assert?
228 return NULL;
229 }
230 }
231
232 // Gives quick access to the length of a string/keyword/name
233 size_t lenstr() const {
234 SkPdfMarkObjectUsed();
235
236 switch (fObjectType) {
237 case kString_PdfObjectType:
238 case kHexString_PdfObjectType:
239 case kKeyword_PdfObjectType:
240 case kName_PdfObjectType:
241 return fStr.fBytes;
242
243 default:
244 // TODO(edisonn): report/warning/assert?
245 return 0;
246 }
247 }
248
249
250 // TODO(edisonn): NYI
251 SkPdfDate& dateValue() const {
252 static SkPdfDate nyi;
253 return nyi;
254 }
255
256 // TODO(edisonn): NYI
257 SkPdfFunction& functionValue() const {
258 static SkPdfFunction nyi;
259 return nyi;
260 }
261
262 // TODO(edisonn): NYI
263 SkPdfFileSpec& fileSpecValue() const {
264 static SkPdfFileSpec nyi;
265 return nyi;
266 }
267
268 // TODO(edisonn): NYI
269 SkPdfTree& treeValue() const {
270 static SkPdfTree nyi;
271 return nyi;
272 }
273
274 // Creates a Boolean object. Assumes and asserts that it was never initializ ed.
275 static void makeBoolean(bool value, SkPdfNativeObject* obj) {
276 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
277
278 obj->fObjectType = kBoolean_PdfObjectType;
279 obj->fBooleanValue = value;
280 }
281
282 static SkPdfNativeObject makeBoolean(bool value) {
283 SkPdfNativeObject obj;
284
285 obj.fObjectType = kBoolean_PdfObjectType;
286 obj.fBooleanValue = value;
287 return obj;
288 }
289
290 // Creates an Integer object. Assumes and asserts that it was never initiali zed.
291 static void makeInteger(int64_t value, SkPdfNativeObject* obj) {
292 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
293
294 obj->fObjectType = kInteger_PdfObjectType;
295 obj->fIntegerValue = value;
296 }
297
298 // Creates a Real object. Assumes and asserts that it was never initialized.
299 static void makeReal(double value, SkPdfNativeObject* obj) {
300 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
301
302 obj->fObjectType = kReal_PdfObjectType;
303 obj->fRealValue = value;
304 }
305
306 // Creates a Null object. Assumes and asserts that it was never initialized.
307 static void makeNull(SkPdfNativeObject* obj) {
308 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
309
310 obj->fObjectType = kNull_PdfObjectType;
311 }
312
313 static SkPdfNativeObject makeNull() {
314 SkPdfNativeObject obj;
315
316 obj.fObjectType = kNull_PdfObjectType;
317 return obj;
318 }
319
320 // TODO(edisonn): this might not woirk well in Chrome
321 static SkPdfNativeObject kNull;
322
323 // Creates a Numeric object from a string. Assumes and asserts that it was n ever initialized.
324 static void makeNumeric(const unsigned char* start, const unsigned char* end ,
325 SkPdfNativeObject* obj) {
326 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
327
328 // TODO(edisonn): NYI properly
329 // if has dot (impl), or exceeds max int, is real, otherwise is int
330 bool isInt = true;
331 for (const unsigned char* current = start; current < end; current++) {
332 if (*current == '.') {
333 isInt = false;
334 break;
335 }
336 // TODO(edisonn): report parse issue with numbers like "24asdasd123"
337 }
338 if (isInt) {
339 makeInteger(atol((const char*)start), obj);
340 } else {
341 makeReal(atof((const char*)start), obj);
342 }
343 }
344
345 // Creates a Reference object. Assumes and asserts that it was never initial ized.
346 static void makeReference(unsigned int id, unsigned int gen, SkPdfNativeObje ct* obj) {
347 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
348
349 obj->fObjectType = kReference_PdfObjectType;
350 obj->fRef.fId = id;
351 obj->fRef.fGen = gen;
352 }
353
354 // Creates a Reference object. Resets the object before use.
355 static void resetAndMakeReference(unsigned int id, unsigned int gen, SkPdfNa tiveObject* obj) {
356 obj->reset();
357 makeReference(id, gen, obj);
358 }
359
360 // Creates a String object. Assumes and asserts that it was never initialize d.
361 static void makeString(const unsigned char* start, SkPdfNativeObject* obj) {
362 makeStringCore(start, strlen((const char*)start), obj, kString_PdfObject Type);
363 }
364
365 // Creates a String object. Assumes and asserts that it was never initialize d.
366 static void makeString(const unsigned char* start, const unsigned char* end,
367 SkPdfNativeObject* obj) {
368 makeStringCore(start, end - start, obj, kString_PdfObjectType);
369 }
370
371 // Creates a String object. Assumes and asserts that it was never initialize d.
372 static void makeString(const unsigned char* start, size_t bytes, SkPdfNative Object* obj) {
373 makeStringCore(start, bytes, obj, kString_PdfObjectType);
374 }
375
376 // Creates a HexString object. Assumes and asserts that it was never initial ized.
377 static void makeHexString(const unsigned char* start, SkPdfNativeObject* obj ) {
378 makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObj ectType);
379 }
380
381 // Creates a HexString object. Assumes and asserts that it was never initial ized.
382 static void makeHexString(const unsigned char* start, const unsigned char* e nd,
383 SkPdfNativeObject* obj) {
384 makeStringCore(start, end - start, obj, kHexString_PdfObjectType);
385 }
386
387 // Creates a HexString object. Assumes and asserts that it was never initial ized.
388 static void makeHexString(const unsigned char* start, size_t bytes, SkPdfNat iveObject* obj) {
389 makeStringCore(start, bytes, obj, kHexString_PdfObjectType);
390 }
391
392 // Creates a Name object. Assumes and asserts that it was never initialized.
393 static void makeName(const unsigned char* start, SkPdfNativeObject* obj) {
394 makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectTy pe);
395 }
396
397 // Creates a Name object. Assumes and asserts that it was never initialized.
398 static void makeName(const unsigned char* start, const unsigned char* end,
399 SkPdfNativeObject* obj) {
400 makeStringCore(start, end - start, obj, kName_PdfObjectType);
401 }
402
403 // Creates a Name object. Assumes and asserts that it was never initialized.
404 static void makeName(const unsigned char* start, size_t bytes, SkPdfNativeOb ject* obj) {
405 makeStringCore(start, bytes, obj, kName_PdfObjectType);
406 }
407
408 // Creates a Keyword object. Assumes and asserts that it was never initializ ed.
409 static void makeKeyword(const unsigned char* start, SkPdfNativeObject* obj) {
410 makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjec tType);
411 }
412
413 // Creates a Keyword object. Assumes and asserts that it was never initializ ed.
414 static void makeKeyword(const unsigned char* start, const unsigned char* end ,
415 SkPdfNativeObject* obj) {
416 makeStringCore(start, end - start, obj, kKeyword_PdfObjectType);
417 }
418
419 // Creates a Keyword object. Assumes and asserts that it was never initializ ed.
420 static void makeKeyword(const unsigned char* start, size_t bytes, SkPdfNativ eObject* obj) {
421 makeStringCore(start, bytes, obj, kKeyword_PdfObjectType);
422 }
423
424 // Creates an empty Array object. Assumes and asserts that it was never init ialized.
425 static void makeEmptyArray(SkPdfNativeObject* obj) {
426 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
427
428 obj->fObjectType = kArray_PdfObjectType;
429 obj->fArray = new SkTDArray<SkPdfNativeObject*>();
430 }
431
432 // Appends an object into the array. Assumes <this> is an array.
433 bool appendInArray(SkPdfNativeObject* obj) {
434 SkASSERT(fObjectType == kArray_PdfObjectType);
435 if (fObjectType != kArray_PdfObjectType) {
436 // TODO(edisonn): report/warning/assert?
437 return false;
438 }
439
440 fArray->push(obj);
441 return true;
442 }
443
444 // Returns the size of an array.
445 size_t size() const {
446 SkPdfMarkObjectUsed();
447
448 SkASSERT(fObjectType == kArray_PdfObjectType);
449
450 return fArray->count();
451 }
452
453 // Returns one object of an array, by index.
454 SkPdfNativeObject* objAtAIndex(int i) {
455 SkPdfMarkObjectUsed();
456
457 SkASSERT(fObjectType == kArray_PdfObjectType);
458
459 return (*fArray)[i];
460 }
461
462 // Returns one object of an array, by index.
463 const SkPdfNativeObject* objAtAIndex(int i) const {
464 SkPdfMarkObjectUsed();
465
466 SkASSERT(fObjectType == kArray_PdfObjectType);
467
468 return (*fArray)[i];
469 }
470
471 // Returns one object of an array, by index.
472 SkPdfNativeObject* operator[](int i) {
473 SkPdfMarkObjectUsed();
474
475 SkASSERT(fObjectType == kArray_PdfObjectType);
476
477 return (*fArray)[i];
478 }
479
480 const SkPdfNativeObject* operator[](int i) const {
481 SkPdfMarkObjectUsed();
482
483 SkASSERT(fObjectType == kArray_PdfObjectType);
484
485 return (*fArray)[i];
486 }
487
488 // Removes the last object in the array.
489 SkPdfNativeObject* removeLastInArray() {
490 SkPdfMarkObjectUsed();
491
492 SkASSERT(fObjectType == kArray_PdfObjectType);
493
494 SkPdfNativeObject* ret = NULL;
495 fArray->pop(&ret);
496
497 return ret;
498 }
499
500 // Creates an empty Dictionary object. Assumes and asserts that it was never initialized.
501 static void makeEmptyDictionary(SkPdfNativeObject* obj) {
502 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
503
504 obj->fObjectType = kDictionary_PdfObjectType;
505 obj->fMap = new SkTDict<SkPdfNativeObject*>(1);
506 obj->fStr.fBuffer = NULL;
507 obj->fStr.fBytes = 0;
508 }
509
510 // TODO(edisonn): perf: get all the possible names from spec, and compute a hash function
511 // that would create no overlaps in the same dictionary
512 // or build a tree of chars that when followed goes to a unique id/index/has h
513 // TODO(edisonn): generate constants like kDictFoo, kNameDict_name
514 // which will be used in code
515 // add function SkPdfFastNameKey key(const char* key);
516 // TODO(edisonn): setting the same key twice, will make the value undefined!
517
518 // this[key] = value;
519 bool set(const SkPdfNativeObject* key, SkPdfNativeObject* value) {
520 SkPdfMarkObjectUsed();
521
522 SkASSERT(fObjectType == kDictionary_PdfObjectType);
523 SkASSERT(key->fObjectType == kName_PdfObjectType);
524
525 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionar y_PdfObjectType) {
526 // TODO(edisonn): report/warn/assert?
527 return false;
528 }
529
530 return set(key->fStr.fBuffer, key->fStr.fBytes, value);
531 }
532
533 // this[key] = value;
534 bool set(const char* key, SkPdfNativeObject* value) {
535 SkPdfMarkObjectUsed();
536
537 return set((const unsigned char*)key, strlen(key), value);
538 }
539
540 // this[key] = value;
541 bool set(const unsigned char* key, size_t len, SkPdfNativeObject* value) {
542 SkPdfMarkObjectUsed();
543
544 SkASSERT(fObjectType == kDictionary_PdfObjectType);
545
546 if (fObjectType != kDictionary_PdfObjectType) {
547 // TODO(edisonn): report/warn/assert.
548 return false;
549 }
550
551 return fMap->set((const char*)key, len, value);
552 }
553
554 // Returns an object from a Dictionary, identified by it's name.
555 SkPdfNativeObject* get(const SkPdfNativeObject* key) {
556 SkPdfMarkObjectUsed();
557
558 SkASSERT(fObjectType == kDictionary_PdfObjectType);
559 SkASSERT(key->fObjectType == kName_PdfObjectType);
560
561 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionar y_PdfObjectType) {
562 // TODO(edisonn): report/warn/assert.
563 return NULL;
564 }
565
566 return get(key->fStr.fBuffer, key->fStr.fBytes);
567 }
568
569 // Returns an object from a Dictionary, identified by it's name.
570 SkPdfNativeObject* get(const char* key) {
571 SkPdfMarkObjectUsed();
572
573 return get((const unsigned char*)key, strlen(key));
574 }
575
576 // Returns an object from a Dictionary, identified by it's name.
577 SkPdfNativeObject* get(const unsigned char* key, size_t len) {
578 SkPdfMarkObjectUsed();
579
580 SkASSERT(fObjectType == kDictionary_PdfObjectType);
581 SkASSERT(key);
582 if (fObjectType != kDictionary_PdfObjectType) {
583 // TODO(edisonn): report/warn/assert.
584 return NULL;
585 }
586 SkPdfNativeObject* ret = NULL;
587 fMap->find((const char*)key, len, &ret);
588
589 #ifdef PDF_TRACE
590 SkString _key;
591 _key.append((const char*)key, len);
592 printf("\nget(/%s) = %s\n", _key.c_str(),
593 ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
594 #endif
595
596 return ret;
597 }
598
599 // Returns an object from a Dictionary, identified by it's name.
600 const SkPdfNativeObject* get(const SkPdfNativeObject* key) const {
601 SkPdfMarkObjectUsed();
602
603 SkASSERT(fObjectType == kDictionary_PdfObjectType);
604 SkASSERT(key->fObjectType == kName_PdfObjectType);
605
606 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionar y_PdfObjectType) {
607 // TODO(edisonn): report/warn/assert.
608 return NULL;
609 }
610
611 return get(key->fStr.fBuffer, key->fStr.fBytes);
612 }
613
614 // Returns an object from a Dictionary, identified by it's name.
615 const SkPdfNativeObject* get(const char* key) const {
616 SkPdfMarkObjectUsed();
617
618 return get((const unsigned char*)key, strlen(key));
619 }
620
621 // Returns an object from a Dictionary, identified by it's name.
622 const SkPdfNativeObject* get(const unsigned char* key, size_t len) const {
623 SkPdfMarkObjectUsed();
624
625 SkASSERT(fObjectType == kDictionary_PdfObjectType);
626 SkASSERT(key);
627 if (fObjectType != kDictionary_PdfObjectType) {
628 // TODO(edisonn): report/warn/assert.
629 return NULL;
630 }
631 SkPdfNativeObject* ret = NULL;
632 fMap->find((const char*)key, len, &ret);
633
634 #ifdef PDF_TRACE
635 SkString _key;
636 _key.append((const char*)key, len);
637 printf("\nget(/%s) = %s\n", _key.c_str(),
638 ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
639 #endif
640
641 return ret;
642 }
643
644 // Returns an object from a Dictionary, identified by it's name.
645 const SkPdfNativeObject* get(const char* key, const char* abr) const {
646 SkPdfMarkObjectUsed();
647
648 const SkPdfNativeObject* ret = get(key);
649 // TODO(edisonn): remove || *abr == '\0' and pass NULL in the _autogen files instead.
650 if (ret != NULL || abr == NULL || *abr == '\0') {
651 return ret;
652 }
653 return get(abr);
654 }
655
656 // Returns an object from a Dictionary, identified by it's name.
657 SkPdfNativeObject* get(const char* key, const char* abr) {
658 SkPdfMarkObjectUsed();
659
660 SkPdfNativeObject* ret = get(key);
661 // TODO(edisonn): remove || *abr == '\0' and pass NULL in the _autogen files instead.
662 if (ret != NULL || abr == NULL || *abr == '\0') {
663 return ret;
664 }
665 return get(abr);
666 }
667
668 // Casts the object to a Dictionary. Asserts if the object is not a Dictiona ry.
669 SkPdfDictionary* asDictionary() {
670 SkPdfMarkObjectUsed();
671
672 SkASSERT(isDictionary());
673 if (!isDictionary()) {
674 return NULL;
675 }
676 return (SkPdfDictionary*) this;
677 }
678
679 // Casts the object to a Dictionary. Asserts if the object is not a Dictiona ry.
680 const SkPdfDictionary* asDictionary() const {
681 SkPdfMarkObjectUsed();
682
683 SkASSERT(isDictionary());
684 if (!isDictionary()) {
685 return NULL;
686 }
687 return (SkPdfDictionary*) this;
688 }
689
690
691 // Returns true if the object is a Reference.
692 bool isReference() const {
693 SkPdfMarkObjectUsed();
694
695 return fObjectType == kReference_PdfObjectType;
696 }
697
698 // Returns true if the object is a Boolean.
699 bool isBoolean() const {
700 SkPdfMarkObjectUsed();
701
702 return fObjectType == kBoolean_PdfObjectType;
703 }
704
705 // Returns true if the object is an Integer.
706 bool isInteger() const {
707 SkPdfMarkObjectUsed();
708
709 return fObjectType == kInteger_PdfObjectType;
710 }
711
712 private:
713 // Returns true if the object is a Real number.
714 bool isReal() const {
715 SkPdfMarkObjectUsed();
716
717 return fObjectType == kReal_PdfObjectType;
718 }
719
720 public:
721 // Returns true if the object is a Number (either Integer or Real).
722 bool isNumber() const {
723 SkPdfMarkObjectUsed();
724
725 return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_Pdf ObjectType;
726 }
727
728 // Returns true if the object is a R keyword (used to identify references, e .g. "10 3 R".
729 bool isKeywordReference() const {
730 SkPdfMarkObjectUsed();
731
732 return fObjectType == kKeyword_PdfObjectType && fStr.fBytes == 1 && fStr .fBuffer[0] == 'R';
733 }
734
735 // Returns true if the object is a Keyword.
736 bool isKeyword() const {
737 SkPdfMarkObjectUsed();
738
739 return fObjectType == kKeyword_PdfObjectType;
740 }
741
742 // Returns true if the object is a given Keyword.
743 bool isKeyword(const char* keyword) const {
744 SkPdfMarkObjectUsed();
745
746 if (!isKeyword()) {
747 return false;
748 }
749
750 if (strlen(keyword) != fStr.fBytes) {
751 return false;
752 }
753
754 if (strncmp(keyword, (const char*)fStr.fBuffer, fStr.fBytes) != 0) {
755 return false;
756 }
757
758 return true;
759 }
760
761 // Returns true if the object is a Name.
762 bool isName() const {
763 SkPdfMarkObjectUsed();
764
765 return fObjectType == kName_PdfObjectType;
766 }
767
768 // Returns true if the object is a given Name.
769 bool isName(const char* name) const {
770 SkPdfMarkObjectUsed();
771
772 return fObjectType == kName_PdfObjectType &&
773 fStr.fBytes == strlen(name) &&
774 strncmp((const char*)fStr.fBuffer, name, fStr.fBytes) == 0;
775 }
776
777 // Returns true if the object is an Array.
778 bool isArray() const {
779 SkPdfMarkObjectUsed();
780
781 return fObjectType == kArray_PdfObjectType;
782 }
783
784 // Returns true if the object is a Date.
785 // TODO(edisonn): NYI
786 bool isDate() const {
787 SkPdfMarkObjectUsed();
788
789 return fObjectType == kString_PdfObjectType || fObjectType == kHexString _PdfObjectType;
790 }
791
792 // Returns true if the object is a Dictionary.
793 bool isDictionary() const {
794 SkPdfMarkObjectUsed();
795
796 return fObjectType == kDictionary_PdfObjectType;
797 }
798
799 // Returns true if the object is a Date.
800 // TODO(edisonn): NYI
801 bool isFunction() const {
802 SkPdfMarkObjectUsed();
803
804 return false; // NYI
805 }
806
807 // Returns true if the object is a Rectangle.
808 bool isRectangle() const {
809 SkPdfMarkObjectUsed();
810
811 // TODO(edisonn): add also that each of these 4 objects are numbers.
812 return fObjectType == kArray_PdfObjectType && fArray->count() == 4;
813 }
814
815 // TODO(edisonn): Design: decide if we should use hasStream or isStream
816 // Returns true if the object has a stream associated with it.
817 bool hasStream() const {
818 SkPdfMarkObjectUsed();
819
820 return isDictionary() && fStr.fBuffer != NULL;
821 }
822
823 // Returns the stream associated with the dictionary. As of now, it casts th is to Stream.
824 const SkPdfStream* getStream() const {
825 SkPdfMarkObjectUsed();
826
827 return hasStream() ? (const SkPdfStream*)this : NULL;
828 }
829
830 // Returns the stream associated with the dictionary. As of now, it casts th is to Stream.
831 SkPdfStream* getStream() {
832 SkPdfMarkObjectUsed();
833
834 return hasStream() ? (SkPdfStream*)this : NULL;
835 }
836
837 // Returns true if the object is a String or HexString.
838 bool isAnyString() const {
839 SkPdfMarkObjectUsed();
840
841 return fObjectType == kString_PdfObjectType || fObjectType == kHexString _PdfObjectType;
842 }
843
844 // Returns true if the object is a HexString.
845 bool isHexString() const {
846 SkPdfMarkObjectUsed();
847
848 return fObjectType == kHexString_PdfObjectType;
849 }
850
851 // Returns true if the object is a Matrix.
852 bool isMatrix() const {
853 SkPdfMarkObjectUsed();
854
855 // TODO(edisonn): add also that each of these 6 objects are numbers.
856 return fObjectType == kArray_PdfObjectType && fArray->count() == 6;
857 }
858
859 // Returns the int value stored in the object. Assert if the object is not a n Integer.
860 inline int64_t intValue() const {
861 SkPdfMarkObjectUsed();
862
863 SkASSERT(fObjectType == kInteger_PdfObjectType);
864
865 if (fObjectType != kInteger_PdfObjectType) {
866 // TODO(edisonn): report/warn/assert.
867 return 0;
868 }
869 return fIntegerValue;
870 }
871
872 private:
873 // Returns the real value stored in the object. Assert if the object is not a Real.
874 inline double realValue() const {
875 SkPdfMarkObjectUsed();
876
877 SkASSERT(fObjectType == kReal_PdfObjectType);
878
879 if (fObjectType != kReal_PdfObjectType) {
880 // TODO(edisonn): report/warn/assert.
881 return 0;
882 }
883 return fRealValue;
884 }
885
886 public:
887 // Returns the numeric value stored in the object. Assert if the object is n ot a Real
888 // or an Integer.
889 inline double numberValue() const {
890 SkPdfMarkObjectUsed();
891
892 SkASSERT(isNumber());
893
894 if (!isNumber()) {
895 // TODO(edisonn): report/warn/assert.
896 return 0;
897 }
898 return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue;
899 }
900
901 // Returns the numeric value stored in the object as a scalar. Assert if the object is not
902 // a Realor an Integer.
903 inline SkScalar scalarValue() const {
904 SkPdfMarkObjectUsed();
905
906 SkASSERT(isNumber());
907
908 if (!isNumber()) {
909 // TODO(edisonn): report/warn/assert.
910 return SkIntToScalar(0);
911 }
912 return fObjectType == kReal_PdfObjectType ? SkDoubleToScalar(fRealValue) :
913 SkIntToScalar(fIntegerValue) ;
914 }
915
916 // Returns the id of the referenced object. Assert if the object is not a Re ference.
917 int referenceId() const {
918 SkPdfMarkObjectUsed();
919
920 SkASSERT(fObjectType == kReference_PdfObjectType);
921 return fRef.fId;
922 }
923
924 // Returns the generation of the referenced object. Assert if the object is not a Reference.
925 int referenceGeneration() const {
926 SkPdfMarkObjectUsed();
927
928 SkASSERT(fObjectType == kReference_PdfObjectType);
929 return fRef.fGen;
930 }
931
932 // Returns the buffer of a Name object. Assert if the object is not a Name.
933 inline const char* nameValue() const {
934 SkPdfMarkObjectUsed();
935
936 SkASSERT(fObjectType == kName_PdfObjectType);
937
938 if (fObjectType != kName_PdfObjectType) {
939 // TODO(edisonn): report/warn/assert.
940 return "";
941 }
942 return (const char*)fStr.fBuffer;
943 }
944
945 // Returns the buffer of a (Hex)String object. Assert if the object is not a (Hex)String.
946 inline const char* stringValue() const {
947 SkPdfMarkObjectUsed();
948
949 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexStri ng_PdfObjectType);
950
951 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_Pd fObjectType) {
952 // TODO(edisonn): report/warn/assert.
953 return "";
954 }
955 return (const char*)fStr.fBuffer;
956 }
957
958 // Returns the storage of any type that can hold a form of string.
959 inline NotOwnedString strRef() {
960 SkPdfMarkObjectUsed();
961
962 switch (fObjectType) {
963 case kString_PdfObjectType:
964 case kHexString_PdfObjectType:
965 case kKeyword_PdfObjectType:
966 case kName_PdfObjectType:
967 return fStr;
968
969 default:
970 // TODO(edisonn): report/warning
971 return NotOwnedString();
972 }
973 }
974
975 // TODO(edisonn): nameValue2 and stringValue2 are used to make code generati on easy,
976 // but it is not a performat way to do it, since it will create an extra cop y
977 // remove these functions and make code generated faster
978 inline SkString nameValue2() const {
979 SkPdfMarkObjectUsed();
980
981 SkASSERT(fObjectType == kName_PdfObjectType);
982
983 if (fObjectType != kName_PdfObjectType) {
984 // TODO(edisonn): log err
985 return SkString();
986 }
987 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
988 }
989
990 // Returns an SkString with the value of the (Hex)String object.
991 inline SkString stringValue2() const {
992 SkPdfMarkObjectUsed();
993
994 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexStri ng_PdfObjectType);
995
996 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_Pd fObjectType) {
997 // TODO(edisonn): report/warn/assert.
998 return SkString();
999 }
1000 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
1001 }
1002
1003 // Returns the boolean of the Bool object. Assert if the object is not a Boo l.
1004 inline bool boolValue() const {
1005 SkPdfMarkObjectUsed();
1006
1007 SkASSERT(fObjectType == kBoolean_PdfObjectType);
1008
1009 if (fObjectType != kBoolean_PdfObjectType) {
1010 // TODO(edisonn): report/warn/assert.
1011 return false;
1012 }
1013 return fBooleanValue;
1014 }
1015
1016 // Returns the rectangle of the Rectangle object. Assert if the object is no t a Rectangle.
1017 SkRect rectangleValue() const {
1018 SkPdfMarkObjectUsed();
1019
1020 SkASSERT(isRectangle());
1021 if (!isRectangle()) {
1022 return SkRect::MakeEmpty();
1023 }
1024
1025 double array[4];
1026 for (int i = 0; i < 4; i++) {
1027 // TODO(edisonn): version where we could resolve references?
1028 const SkPdfNativeObject* elem = objAtAIndex(i);
1029 if (elem == NULL || !elem->isNumber()) {
1030 // TODO(edisonn): report/warn/assert.
1031 return SkRect::MakeEmpty();
1032 }
1033 array[i] = elem->numberValue();
1034 }
1035
1036 return SkRect::MakeLTRB(SkDoubleToScalar(array[0]),
1037 SkDoubleToScalar(array[1]),
1038 SkDoubleToScalar(array[2]),
1039 SkDoubleToScalar(array[3]));
1040 }
1041
1042 // Returns the matrix of the Matrix object. Assert if the object is not a Ma trix.
1043 SkMatrix matrixValue() const {
1044 SkPdfMarkObjectUsed();
1045
1046 SkASSERT(isMatrix());
1047 if (!isMatrix()) {
1048 return SkMatrix::I();
1049 }
1050
1051 double array[6];
1052 for (int i = 0; i < 6; i++) {
1053 // TODO(edisonn): version where we could resolve references?
1054 const SkPdfNativeObject* elem = objAtAIndex(i);
1055 if (elem == NULL || !elem->isNumber()) {
1056 // TODO(edisonn): report/warn/assert.
1057 return SkMatrix::I();
1058 }
1059 array[i] = elem->numberValue();
1060 }
1061
1062 return SkMatrixFromPdfMatrix(array);
1063 }
1064
1065 // Runs all the filters of this stream, except the last one, if it is a DCT.
1066 // Returns false on failure.
1067 bool filterStream();
1068
1069 // Runs all the filters of this stream, except the last one, if it is a DCT, a gives back
1070 // the buffer and the length. The object continues to own the buffer.
1071 // Returns false on failure.
1072 bool GetFilteredStreamRef(unsigned char const** buffer, size_t* len) {
1073 SkPdfMarkObjectUsed();
1074
1075 // TODO(edisonn): add params that could let the last filter in place
1076 // if it is jpeg or png to fast load images.
1077 if (!hasStream()) {
1078 return false;
1079 }
1080
1081 filterStream();
1082
1083 if (buffer) {
1084 *buffer = fStr.fBuffer;
1085 }
1086
1087 if (len) {
1088 *len = fStr.fBytes >> 2; // last 2 bits - TODO(edisonn): clean up.
1089 }
1090
1091 return true;
1092 }
1093
1094 // Returns true if the stream is already filtered.
1095 bool isStreamFiltered() const {
1096 SkPdfMarkObjectUsed();
1097
1098 return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit);
1099 }
1100
1101 // Returns true if this object own the buffer, or false if an Allocator own it.
1102 bool isStreamOwned() const {
1103 SkPdfMarkObjectUsed();
1104
1105 return hasStream() && ((fStr.fBytes & 2) == kOwnedStreamBit);
1106 }
1107
1108 // Gives back the original buffer and the length. The object continues to ow n the buffer.
1109 // Returns false if the stream is already filtered.
1110 bool GetUnfilteredStreamRef(unsigned char const** buffer, size_t* len) const {
1111 SkPdfMarkObjectUsed();
1112
1113 if (isStreamFiltered()) {
1114 return false;
1115 }
1116
1117 if (!hasStream()) {
1118 return false;
1119 }
1120
1121 if (buffer) {
1122 *buffer = fStr.fBuffer;
1123 }
1124
1125 if (len) {
1126 *len = fStr.fBytes >> 2; // remove last 2 bits - TODO(edisonn): cle an up.
1127 }
1128
1129 return true;
1130 }
1131
1132 // Add a stream to this Dictionarry. Asserts we do not have yet a stream.
1133 bool addStream(const unsigned char* buffer, size_t len) {
1134 SkPdfMarkObjectUsed();
1135
1136 SkASSERT(!hasStream());
1137 SkASSERT(isDictionary());
1138
1139 if (!isDictionary() || hasStream()) {
1140 return false;
1141 }
1142
1143 fStr.fBuffer = buffer;
1144 fStr.fBytes = (len << 2) + kUnfilteredStreamBit;
1145
1146 return true;
1147 }
1148
1149 static void appendSpaces(SkString* str, int level) {
1150 for (int i = 0 ; i < level; i++) {
1151 str->append(" ");
1152 }
1153 }
1154
1155 static void append(SkString* str, const char* data, size_t len, const char* prefix = "\\x") {
1156 for (unsigned int i = 0 ; i < len; i++) {
1157 if (data[i] == kNUL_PdfWhiteSpace) {
1158 str->append(prefix);
1159 str->append("00");
1160 } else if (data[i] == kHT_PdfWhiteSpace) {
1161 str->append(prefix);
1162 str->append("09");
1163 } else if (data[i] == kLF_PdfWhiteSpace) {
1164 str->append(prefix);
1165 str->append("0A");
1166 } else if (data[i] == kFF_PdfWhiteSpace) {
1167 str->append(prefix);
1168 str->append("0C");
1169 } else if (data[i] == kCR_PdfWhiteSpace) {
1170 str->append(prefix);
1171 str->append("0D");
1172 } else {
1173 str->append(data + i, 1);
1174 }
1175 }
1176 }
1177
1178 // Returns the string representation of the object value.
1179 SkString toString(int firstRowLevel = 0, int level = 0) {
1180 SkString str;
1181 appendSpaces(&str, firstRowLevel);
1182 switch (fObjectType) {
1183 case kInvalid_PdfObjectType:
1184 str.append("__Invalid");
1185 break;
1186
1187 case kBoolean_PdfObjectType:
1188 str.appendf("%s", fBooleanValue ? "true" : "false");
1189 break;
1190
1191 case kInteger_PdfObjectType:
1192 str.appendf("%i", (int)fIntegerValue);
1193 break;
1194
1195 case kReal_PdfObjectType:
1196 str.appendf("%f", fRealValue);
1197 break;
1198
1199 case kString_PdfObjectType:
1200 str.append("\"");
1201 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
1202 str.append("\"");
1203 break;
1204
1205 case kHexString_PdfObjectType:
1206 str.append("<");
1207 for (unsigned int i = 0 ; i < fStr.fBytes; i++) {
1208 str.appendf("%02x", (unsigned int)fStr.fBuffer[i]);
1209 }
1210 str.append(">");
1211 break;
1212
1213 case kName_PdfObjectType:
1214 str.append("/");
1215 append(&str, (const char*)fStr.fBuffer, fStr.fBytes, "#");
1216 break;
1217
1218 case kKeyword_PdfObjectType:
1219 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
1220 break;
1221
1222 case kArray_PdfObjectType:
1223 str.append("[\n");
1224 for (unsigned int i = 0; i < size(); i++) {
1225 str.append(objAtAIndex(i)->toString(level + 1, level + 1));
1226 if (i < size() - 1) {
1227 str.append(",");
1228 }
1229 str.append("\n");
1230 }
1231 appendSpaces(&str, level);
1232 str.append("]");
1233 break;
1234
1235 case kDictionary_PdfObjectType: {
1236 SkTDict<SkPdfNativeObject*>::Iter iter(*fMap);
1237 SkPdfNativeObject* obj = NULL;
1238 const char* key = NULL;
1239 str.append("<<\n");
1240 while ((key = iter.next(&obj)) != NULL) {
1241 appendSpaces(&str, level + 2);
1242 str.appendf("/%s %s\n", key,
1243 obj->toString(0, level + (int) strlen(key) + 4).c_str());
1244 }
1245 appendSpaces(&str, level);
1246 str.append(">>");
1247 if (hasStream()) {
1248 const unsigned char* stream = NULL;
1249 size_t length = 0;
1250 if (GetFilteredStreamRef(&stream, &length)) {
1251 str.append("stream\n");
1252 append(&str, (const char*)stream, length > 256 ? 256 : length);
1253 str.append("\nendstream");
1254 } else {
1255 str.append("stream STREAM_ERROR endstream");
1256 }
1257 }
1258 }
1259 break;
1260
1261 case kNull_PdfObjectType:
1262 str = "NULL";
1263 break;
1264
1265 case kReference_PdfObjectType:
1266 str.appendf("%i %i R", fRef.fId, fRef.fGen);
1267 break;
1268
1269 case kUndefined_PdfObjectType:
1270 str = "Undefined";
1271 break;
1272
1273 default:
1274 str = "Error";
1275 break;
1276 }
1277
1278 return str;
1279 }
1280
1281 private:
1282 static void makeStringCore(const unsigned char* start, SkPdfNativeObject* ob j,
1283 ObjectType type) {
1284 makeStringCore(start, strlen((const char*)start), obj, type);
1285 }
1286
1287 static void makeStringCore(const unsigned char* start, const unsigned char* end,
1288 SkPdfNativeObject* obj, ObjectType type) {
1289 makeStringCore(start, end - start, obj, type);
1290 }
1291
1292 static void makeStringCore(const unsigned char* start, size_t bytes, SkPdfNa tiveObject* obj,
1293 ObjectType type) {
1294 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
1295
1296 obj->fObjectType = type;
1297 obj->fStr.fBuffer = start;
1298 obj->fStr.fBytes = bytes;
1299 }
1300
1301 bool applyFilter(const char* name);
1302 bool applyFlateDecodeFilter();
1303 bool applyDCTDecodeFilter();
1304 };
1305
1306 // These classes are provided for convenience. You still have to make sure an Sk PdfInteger
1307 // is indeed an Integer.
1308 class SkPdfStream : public SkPdfNativeObject {};
1309 class SkPdfArray : public SkPdfNativeObject {};
1310 class SkPdfString : public SkPdfNativeObject {};
1311 class SkPdfHexString : public SkPdfNativeObject {};
1312 class SkPdfInteger : public SkPdfNativeObject {};
1313 class SkPdfReal : public SkPdfNativeObject {};
1314 class SkPdfNumber : public SkPdfNativeObject {};
1315
1316 class SkPdfName : public SkPdfNativeObject {
1317 SkPdfName() : SkPdfNativeObject() {
1318 SkPdfNativeObject::makeName((const unsigned char*)"", this);
1319 }
1320 public:
1321 SkPdfName(char* name) : SkPdfNativeObject() {
1322 this->makeName((const unsigned char*)name, this);
1323 }
1324 };
1325
1326 #endif // SkPdfNativeObject
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698