blob: f26b53b8bd2ae0b6f01f229dba3f0011128d6c8a [file] [log] [blame]
edisonn@google.comcf2cfa12013-08-21 16:31:37 +00001/*
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
edisonn@google.com571c70b2013-07-10 17:09:50 +000010
11#include <stdint.h>
12#include <string.h>
edisonn@google.com063d7072013-08-16 15:05:08 +000013#include "SkString.h"
edisonn@google.com571c70b2013-07-10 17:09:50 +000014#include "SkTDArray.h"
15#include "SkTDict.h"
16#include "SkRect.h"
17#include "SkMatrix.h"
18#include "SkString.h"
19
20#include "SkPdfNYI.h"
21#include "SkPdfConfig.h"
edisonn@google.com3aa35552013-08-14 18:26:20 +000022#include "SkPdfUtils.h"
23
24#include "SkPdfNativeTokenizer.h"
edisonn@google.com571c70b2013-07-10 17:09:50 +000025
26class SkPdfDictionary;
27class SkPdfStream;
28class SkPdfAllocator;
29
30// TODO(edisonn): macro it and move it to utils
31SkMatrix SkMatrixFromPdfMatrix(double array[6]);
32
33
34#define kFilteredStreamBit 0
35#define kUnfilteredStreamBit 1
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000036#define kOwnedStreamBit 2
edisonn@google.com571c70b2013-07-10 17:09:50 +000037
edisonn@google.com3aa35552013-08-14 18:26:20 +000038class SkPdfNativeObject {
edisonn@google.com571c70b2013-07-10 17:09:50 +000039 public:
40 enum ObjectType {
41 kInvalid_PdfObjectType,
42
43 kBoolean_PdfObjectType,
44 kInteger_PdfObjectType,
45 kReal_PdfObjectType,
46 kString_PdfObjectType,
47 kHexString_PdfObjectType,
48 kName_PdfObjectType,
49 kKeyword_PdfObjectType,
50 //kStream_PdfObjectType, // attached to a Dictionary
51 kArray_PdfObjectType,
52 kDictionary_PdfObjectType,
53 kNull_PdfObjectType,
54
55 // TODO(edisonn): after the pdf has been loaded completely, resolve all references
56 // try the same thing with delayed loaded ...
57 kReference_PdfObjectType,
58
59 kUndefined_PdfObjectType, // per 1.4 spec, if the same key appear twice in the dictionary, the value is undefined
60 };
61
edisonn@google.comb0145ce2013-08-05 16:23:23 +000062 enum DataType {
63 kEmpty_Data,
64 kFont_Data,
65 kBitmap_Data,
66 };
67
edisonn@google.com571c70b2013-07-10 17:09:50 +000068private:
edisonn@google.com063d7072013-08-16 15:05:08 +000069 // TODO(edisonn): assert reset operations while in rendering!
70 uint32_t fInRendering : 1;
71 uint32_t fUnused : 31;
72
73
edisonn@google.com571c70b2013-07-10 17:09:50 +000074 struct Reference {
75 unsigned int fId;
76 unsigned int fGen;
77 };
78
79 // TODO(edisonn): add stream start, stream end, where stream is weither the file
80 // or decoded/filtered pdf stream
81
82 // TODO(edisonn): add warning/report per object
83 // TODO(edisonn): add flag fUsed, to be used once the parsing is complete,
84 // so we could show what parts have been proccessed, ignored, or generated errors
85
86 ObjectType fObjectType;
87
88 union {
89 bool fBooleanValue;
90 int64_t fIntegerValue;
91 // TODO(edisonn): double, float? typedefed
92 double fRealValue;
93 NotOwnedString fStr;
94
95 // TODO(edisonn): make sure the foorprint of fArray and fMap is small, otherwise, use pointers, or classes with up to 8 bytes in footprint
edisonn@google.com3aa35552013-08-14 18:26:20 +000096 SkTDArray<SkPdfNativeObject*>* fArray;
edisonn@google.com571c70b2013-07-10 17:09:50 +000097 Reference fRef;
98 };
edisonn@google.com3aa35552013-08-14 18:26:20 +000099 SkTDict<SkPdfNativeObject*>* fMap;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000100
101 // TODO(edisonn): rename data with cache
edisonn@google.com571c70b2013-07-10 17:09:50 +0000102 void* fData;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000103 DataType fDataType;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000104
105
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000106 // Keep this the last entrys
107#ifdef PDF_TRACK_OBJECT_USAGE
108 mutable bool fUsed;
109#endif // PDF_TRACK_OBJECT_USAGE
110
edisonn@google.com571c70b2013-07-10 17:09:50 +0000111public:
112
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000113 SkPdfNativeObject() : fInRendering(0)
114 , fObjectType(kInvalid_PdfObjectType)
115 , fMap(NULL)
116 , fData(NULL)
117 , fDataType(kEmpty_Data)
118#ifdef PDF_TRACK_OBJECT_USAGE
119 , fUsed(false)
120#endif // PDF_TRACK_OBJECT_USAGE
121 {}
edisonn@google.com571c70b2013-07-10 17:09:50 +0000122
edisonn@google.com063d7072013-08-16 15:05:08 +0000123 bool inRendering() const { return fInRendering != 0; }
124 void startRendering() {fInRendering = 1;}
125 void doneRendering() {fInRendering = 0;}
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000126
127 inline bool hasData(DataType type) {
128 return type == fDataType;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000129 }
130
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000131 inline void* data(DataType type) {
132 return type == fDataType ? fData : NULL;
133 }
134
135 inline void setData(void* data, DataType type) {
136 releaseData();
137 fDataType = type;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000138 fData = data;
139 }
140
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000141 void releaseData();
142
edisonn@google.com3aa35552013-08-14 18:26:20 +0000143// ~SkPdfNativeObject() {
edisonn@google.com222382b2013-07-10 22:33:10 +0000144// //reset(); must be called manually!
145// }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000146
147 void reset() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000148 SkPdfMarkObjectUnused();
149
edisonn@google.com571c70b2013-07-10 17:09:50 +0000150 switch (fObjectType) {
151 case kArray_PdfObjectType:
152 delete fArray;
153 break;
154
155 case kDictionary_PdfObjectType:
156 delete fMap;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000157 if (isStreamOwned()) {
158 delete[] fStr.fBuffer;
159 fStr.fBuffer = NULL;
160 fStr.fBytes = 0;
161 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000162 break;
163
164 default:
165 break;
166 }
167 fObjectType = kInvalid_PdfObjectType;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000168 releaseData();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000169 }
170
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000171 ObjectType type() {
172 SkPdfMarkObjectUsed();
173
174 return fObjectType;
175 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000176
177 const char* c_str() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000178 SkPdfMarkObjectUsed();
179
edisonn@google.com571c70b2013-07-10 17:09:50 +0000180 switch (fObjectType) {
181 case kString_PdfObjectType:
182 case kHexString_PdfObjectType:
183 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000184 case kName_PdfObjectType:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000185 return (const char*)fStr.fBuffer;
186
187 default:
188 // TODO(edisonn): report/warning
189 return NULL;
190 }
191 }
192
edisonn@google.come878e722013-07-29 19:10:58 +0000193 size_t lenstr() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000194 SkPdfMarkObjectUsed();
195
edisonn@google.com571c70b2013-07-10 17:09:50 +0000196 switch (fObjectType) {
197 case kString_PdfObjectType:
198 case kHexString_PdfObjectType:
199 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000200 case kName_PdfObjectType:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000201 return fStr.fBytes;
202
203 default:
204 // TODO(edisonn): report/warning
205 return 0;
206 }
207 }
208
209
210 // TODO(edisonn): NYI
211 SkPdfDate& dateValue() const {
212 static SkPdfDate nyi;
213 return nyi;
214 }
215
216 // TODO(edisonn): NYI
217 SkPdfFunction& functionValue() const {
218 static SkPdfFunction nyi;
219 return nyi;
220 }
221
222 // TODO(edisonn): NYI
223 SkPdfFileSpec& fileSpecValue() const {
224 static SkPdfFileSpec nyi;
225 return nyi;
226 }
227
228 // TODO(edisonn): NYI
229 SkPdfTree& treeValue() const {
230 static SkPdfTree nyi;
231 return nyi;
232 }
233
edisonn@google.com3aa35552013-08-14 18:26:20 +0000234 static void makeBoolean(bool value, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000235 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
236
237 obj->fObjectType = kBoolean_PdfObjectType;
238 obj->fBooleanValue = value;
239 }
240
edisonn@google.com3aa35552013-08-14 18:26:20 +0000241 static SkPdfNativeObject makeBoolean(bool value) {
242 SkPdfNativeObject obj;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000243 obj.fObjectType = kBoolean_PdfObjectType;
244 obj.fBooleanValue = value;
245 return obj;
246 }
247
edisonn@google.com3aa35552013-08-14 18:26:20 +0000248 static void makeInteger(int64_t value, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000249 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
250
251 obj->fObjectType = kInteger_PdfObjectType;
252 obj->fIntegerValue = value;
253 }
254
edisonn@google.com3aa35552013-08-14 18:26:20 +0000255 static void makeReal(double value, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000256 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
257
258 obj->fObjectType = kReal_PdfObjectType;
259 obj->fRealValue = value;
260 }
261
edisonn@google.com3aa35552013-08-14 18:26:20 +0000262 static void makeNull(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000263 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
264
265 obj->fObjectType = kNull_PdfObjectType;
266 }
267
edisonn@google.com3aa35552013-08-14 18:26:20 +0000268 static SkPdfNativeObject makeNull() {
269 SkPdfNativeObject obj;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000270 obj.fObjectType = kNull_PdfObjectType;
271 return obj;
272 }
273
edisonn@google.com3aa35552013-08-14 18:26:20 +0000274 static SkPdfNativeObject kNull;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000275
edisonn@google.com3aa35552013-08-14 18:26:20 +0000276 static void makeNumeric(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000277 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
278
279 // TODO(edisonn): NYI properly
280 // if has dot (impl), or exceeds max int, is real, otherwise is int
281 bool isInt = true;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000282 for (const unsigned char* current = start; current < end; current++) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000283 if (*current == '.') {
284 isInt = false;
285 break;
286 }
287 // TODO(edisonn): report parse issue with numbers like "24asdasd123"
288 }
289 if (isInt) {
290 makeInteger(atol((const char*)start), obj);
291 } else {
292 makeReal(atof((const char*)start), obj);
293 }
294 }
295
edisonn@google.com3aa35552013-08-14 18:26:20 +0000296 static void makeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000297 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
298
299 obj->fObjectType = kReference_PdfObjectType;
300 obj->fRef.fId = id;
301 obj->fRef.fGen = gen;
302 }
303
304
edisonn@google.com3aa35552013-08-14 18:26:20 +0000305 static void makeString(const unsigned char* start, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000306 makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType);
307 }
308
edisonn@google.com3aa35552013-08-14 18:26:20 +0000309 static void makeString(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000310 makeStringCore(start, end - start, obj, kString_PdfObjectType);
311 }
312
edisonn@google.com3aa35552013-08-14 18:26:20 +0000313 static void makeString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000314 makeStringCore(start, bytes, obj, kString_PdfObjectType);
315 }
316
317
edisonn@google.com3aa35552013-08-14 18:26:20 +0000318 static void makeHexString(const unsigned char* start, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000319 makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType);
320 }
321
edisonn@google.com3aa35552013-08-14 18:26:20 +0000322 static void makeHexString(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000323 makeStringCore(start, end - start, obj, kHexString_PdfObjectType);
324 }
325
edisonn@google.com3aa35552013-08-14 18:26:20 +0000326 static void makeHexString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000327 makeStringCore(start, bytes, obj, kHexString_PdfObjectType);
328 }
329
330
edisonn@google.com3aa35552013-08-14 18:26:20 +0000331 static void makeName(const unsigned char* start, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000332 makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType);
333 }
334
edisonn@google.com3aa35552013-08-14 18:26:20 +0000335 static void makeName(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000336 makeStringCore(start, end - start, obj, kName_PdfObjectType);
337 }
338
edisonn@google.com3aa35552013-08-14 18:26:20 +0000339 static void makeName(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000340 makeStringCore(start, bytes, obj, kName_PdfObjectType);
341 }
342
343
edisonn@google.com3aa35552013-08-14 18:26:20 +0000344 static void makeKeyword(const unsigned char* start, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000345 makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType);
346 }
347
edisonn@google.com3aa35552013-08-14 18:26:20 +0000348 static void makeKeyword(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000349 makeStringCore(start, end - start, obj, kKeyword_PdfObjectType);
350 }
351
edisonn@google.com3aa35552013-08-14 18:26:20 +0000352 static void makeKeyword(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000353 makeStringCore(start, bytes, obj, kKeyword_PdfObjectType);
354 }
355
356
357
358 // TODO(edisonn): make the functions to return SkPdfArray, move these functions in SkPdfArray
edisonn@google.com3aa35552013-08-14 18:26:20 +0000359 static void makeEmptyArray(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000360 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
361
362 obj->fObjectType = kArray_PdfObjectType;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000363 obj->fArray = new SkTDArray<SkPdfNativeObject*>();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000364 // return (SkPdfArray*)obj;
365 }
366
edisonn@google.com3aa35552013-08-14 18:26:20 +0000367 bool appendInArray(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000368 SkASSERT(fObjectType == kArray_PdfObjectType);
369 if (fObjectType != kArray_PdfObjectType) {
370 // TODO(edisonn): report err
371 return false;
372 }
373
374 fArray->push(obj);
375 return true;
376 }
377
378 size_t size() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000379 SkPdfMarkObjectUsed();
380
edisonn@google.com571c70b2013-07-10 17:09:50 +0000381 SkASSERT(fObjectType == kArray_PdfObjectType);
382
383 return fArray->count();
384 }
385
edisonn@google.com3aa35552013-08-14 18:26:20 +0000386 SkPdfNativeObject* objAtAIndex(int i) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000387 SkPdfMarkObjectUsed();
388
edisonn@google.com571c70b2013-07-10 17:09:50 +0000389 SkASSERT(fObjectType == kArray_PdfObjectType);
390
391 return (*fArray)[i];
392 }
393
edisonn@google.com3aa35552013-08-14 18:26:20 +0000394 SkPdfNativeObject* removeLastInArray() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000395 // SkPdfMarkObjectUsed();
396
edisonn@google.com571c70b2013-07-10 17:09:50 +0000397 SkASSERT(fObjectType == kArray_PdfObjectType);
398
edisonn@google.com3aa35552013-08-14 18:26:20 +0000399 SkPdfNativeObject* ret = NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000400 fArray->pop(&ret);
401
402 return ret;
403 }
404
405
edisonn@google.com3aa35552013-08-14 18:26:20 +0000406 const SkPdfNativeObject* objAtAIndex(int i) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000407 SkPdfMarkObjectUsed();
408
edisonn@google.com571c70b2013-07-10 17:09:50 +0000409 SkASSERT(fObjectType == kArray_PdfObjectType);
410
411 return (*fArray)[i];
412 }
413
edisonn@google.com3aa35552013-08-14 18:26:20 +0000414 SkPdfNativeObject* operator[](int i) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000415 SkASSERT(fObjectType == kArray_PdfObjectType);
416
417 return (*fArray)[i];
418 }
419
edisonn@google.com3aa35552013-08-14 18:26:20 +0000420 const SkPdfNativeObject* operator[](int i) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000421 SkPdfMarkObjectUsed();
422
edisonn@google.com571c70b2013-07-10 17:09:50 +0000423 SkASSERT(fObjectType == kArray_PdfObjectType);
424
425 return (*fArray)[i];
426 }
427
428
429 // TODO(edisonn): make the functions to return SkPdfDictionary, move these functions in SkPdfDictionary
edisonn@google.com3aa35552013-08-14 18:26:20 +0000430 static void makeEmptyDictionary(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000431 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
432
433 obj->fObjectType = kDictionary_PdfObjectType;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000434 obj->fMap = new SkTDict<SkPdfNativeObject*>(1);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000435 obj->fStr.fBuffer = NULL;
436 obj->fStr.fBytes = 0;
437 }
438
439 // TODO(edisonn): get all the possible names from spec, and compute a hash function
440 // that would create no overlaps in the same dictionary
441 // or build a tree of chars that when followed goes to a unique id/index/hash
442 // TODO(edisonn): generate constants like kDictFoo, kNameDict_name
443 // which will be used in code
444 // add function SkPdfFastNameKey key(const char* key);
445 // TODO(edisonn): setting the same key twike, will make the value undefined!
edisonn@google.com3aa35552013-08-14 18:26:20 +0000446 bool set(const SkPdfNativeObject* key, SkPdfNativeObject* value) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000447 //SkPdfMarkObjectUsed();
448
edisonn@google.com571c70b2013-07-10 17:09:50 +0000449 SkASSERT(fObjectType == kDictionary_PdfObjectType);
450 SkASSERT(key->fObjectType == kName_PdfObjectType);
451
452 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
453 // TODO(edisonn): report err
454 return false;
455 }
456
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000457 //// we rewrite all delimiters and white spaces with '\0', so we expect the end of name to be '\0'
458 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
edisonn@google.com571c70b2013-07-10 17:09:50 +0000459
edisonn@google.comd761e322013-07-22 17:29:43 +0000460 return set(key->fStr.fBuffer, key->fStr.fBytes, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000461 }
462
edisonn@google.com3aa35552013-08-14 18:26:20 +0000463 bool set(const char* key, SkPdfNativeObject* value) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000464 //SkPdfMarkObjectUsed();
465
edisonn@google.comd761e322013-07-22 17:29:43 +0000466 return set((const unsigned char*)key, strlen(key), value);
467 }
468
edisonn@google.com3aa35552013-08-14 18:26:20 +0000469 bool set(const unsigned char* key, size_t len, SkPdfNativeObject* value) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000470 //SkPdfMarkObjectUsed();
471
edisonn@google.com571c70b2013-07-10 17:09:50 +0000472 SkASSERT(fObjectType == kDictionary_PdfObjectType);
473
474 if (fObjectType != kDictionary_PdfObjectType) {
475 // TODO(edisonn): report err
476 return false;
477 }
478
edisonn@google.comd761e322013-07-22 17:29:43 +0000479 return fMap->set((const char*)key, len, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000480 }
481
edisonn@google.com3aa35552013-08-14 18:26:20 +0000482 SkPdfNativeObject* get(const SkPdfNativeObject* key) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000483 SkPdfMarkObjectUsed();
484
edisonn@google.com571c70b2013-07-10 17:09:50 +0000485 SkASSERT(fObjectType == kDictionary_PdfObjectType);
486 SkASSERT(key->fObjectType == kName_PdfObjectType);
487
488 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
489 // TODO(edisonn): report err
edisonn@google.com3fc48262013-07-22 15:29:55 +0000490 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000491 }
492
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000493 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
edisonn@google.com571c70b2013-07-10 17:09:50 +0000494
edisonn@google.comd761e322013-07-22 17:29:43 +0000495 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000496 }
497
edisonn@google.com3aa35552013-08-14 18:26:20 +0000498 SkPdfNativeObject* get(const char* key) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000499 SkPdfMarkObjectUsed();
500
edisonn@google.comd761e322013-07-22 17:29:43 +0000501 return get((const unsigned char*)key, strlen(key));
502 }
503
edisonn@google.com3aa35552013-08-14 18:26:20 +0000504 SkPdfNativeObject* get(const unsigned char* key, size_t len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000505 SkPdfMarkObjectUsed();
506
edisonn@google.com571c70b2013-07-10 17:09:50 +0000507 SkASSERT(fObjectType == kDictionary_PdfObjectType);
508 SkASSERT(key);
509 if (fObjectType != kDictionary_PdfObjectType) {
510 // TODO(edisonn): report err
511 return NULL;
512 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000513 SkPdfNativeObject* ret = NULL;
edisonn@google.comd761e322013-07-22 17:29:43 +0000514 fMap->find((const char*)key, len, &ret);
edisonn@google.com9a43c182013-08-01 20:06:42 +0000515
516#ifdef PDF_TRACE
517 SkString _key;
518 _key.append((const char*)key, len);
519 printf("\nget(/%s) = %s\n", _key.c_str(), ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
520#endif
521
edisonn@google.com571c70b2013-07-10 17:09:50 +0000522 return ret;
523 }
524
edisonn@google.com3aa35552013-08-14 18:26:20 +0000525 const SkPdfNativeObject* get(const SkPdfNativeObject* key) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000526 SkPdfMarkObjectUsed();
527
edisonn@google.com571c70b2013-07-10 17:09:50 +0000528 SkASSERT(fObjectType == kDictionary_PdfObjectType);
529 SkASSERT(key->fObjectType == kName_PdfObjectType);
530
531 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
532 // TODO(edisonn): report err
edisonn@google.com3fc48262013-07-22 15:29:55 +0000533 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000534 }
535
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000536 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
edisonn@google.com571c70b2013-07-10 17:09:50 +0000537
edisonn@google.comd761e322013-07-22 17:29:43 +0000538 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000539 }
540
edisonn@google.com3aa35552013-08-14 18:26:20 +0000541 const SkPdfNativeObject* get(const char* key) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000542 SkPdfMarkObjectUsed();
543
edisonn@google.comd761e322013-07-22 17:29:43 +0000544 return get((const unsigned char*)key, strlen(key));
545 }
546
edisonn@google.com3aa35552013-08-14 18:26:20 +0000547 const SkPdfNativeObject* get(const unsigned char* key, size_t len) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000548 SkPdfMarkObjectUsed();
549
edisonn@google.com571c70b2013-07-10 17:09:50 +0000550 SkASSERT(fObjectType == kDictionary_PdfObjectType);
551 SkASSERT(key);
552 if (fObjectType != kDictionary_PdfObjectType) {
553 // TODO(edisonn): report err
554 return NULL;
555 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000556 SkPdfNativeObject* ret = NULL;
edisonn@google.comd761e322013-07-22 17:29:43 +0000557 fMap->find((const char*)key, len, &ret);
edisonn@google.com9a43c182013-08-01 20:06:42 +0000558
559#ifdef PDF_TRACE
560 SkString _key;
561 _key.append((const char*)key, len);
562 printf("\nget(/%s) = %s\n", _key.c_str(), ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
563#endif
564
edisonn@google.com571c70b2013-07-10 17:09:50 +0000565 return ret;
566 }
567
edisonn@google.com3aa35552013-08-14 18:26:20 +0000568 const SkPdfNativeObject* get(const char* key, const char* abr) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000569 SkPdfMarkObjectUsed();
570
edisonn@google.com3aa35552013-08-14 18:26:20 +0000571 const SkPdfNativeObject* ret = get(key);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000572 // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL
573 // make this distiontion in generator, and remove "" from condition
574 if (ret != NULL || abr == NULL || *abr == '\0') {
575 return ret;
576 }
577 return get(abr);
578 }
579
edisonn@google.com3aa35552013-08-14 18:26:20 +0000580 SkPdfNativeObject* get(const char* key, const char* abr) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000581 SkPdfMarkObjectUsed();
582
edisonn@google.com3aa35552013-08-14 18:26:20 +0000583 SkPdfNativeObject* ret = get(key);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000584 // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL
585 // make this distiontion in generator, and remove "" from condition
586 if (ret != NULL || abr == NULL || *abr == '\0') {
587 return ret;
588 }
589 return get(abr);
590 }
591
592 SkPdfDictionary* asDictionary() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000593 SkPdfMarkObjectUsed();
594
edisonn@google.com571c70b2013-07-10 17:09:50 +0000595 SkASSERT(isDictionary());
596 if (!isDictionary()) {
597 return NULL;
598 }
599 return (SkPdfDictionary*) this;
600 }
601
602 const SkPdfDictionary* asDictionary() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000603 SkPdfMarkObjectUsed();
604
edisonn@google.com571c70b2013-07-10 17:09:50 +0000605 SkASSERT(isDictionary());
606 if (!isDictionary()) {
607 return NULL;
608 }
609 return (SkPdfDictionary*) this;
610 }
611
612
613 bool isReference() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000614 SkPdfMarkObjectUsed();
615
edisonn@google.com571c70b2013-07-10 17:09:50 +0000616 return fObjectType == kReference_PdfObjectType;
617 }
618
619 bool isBoolean() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000620 SkPdfMarkObjectUsed();
621
edisonn@google.com571c70b2013-07-10 17:09:50 +0000622 return fObjectType == kBoolean_PdfObjectType;
623 }
624
625 bool isInteger() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000626 SkPdfMarkObjectUsed();
627
edisonn@google.com571c70b2013-07-10 17:09:50 +0000628 return fObjectType == kInteger_PdfObjectType;
629 }
630private:
631 bool isReal() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000632 SkPdfMarkObjectUsed();
633
edisonn@google.com571c70b2013-07-10 17:09:50 +0000634 return fObjectType == kReal_PdfObjectType;
635 }
636public:
637 bool isNumber() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000638 SkPdfMarkObjectUsed();
639
edisonn@google.com571c70b2013-07-10 17:09:50 +0000640 return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_PdfObjectType;
641 }
642
643 bool isKeywordReference() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000644 SkPdfMarkObjectUsed();
645
edisonn@google.com571c70b2013-07-10 17:09:50 +0000646 return fObjectType == kKeyword_PdfObjectType && fStr.fBytes == 1 && fStr.fBuffer[0] == 'R';
647 }
648
649 bool isKeyword() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000650 SkPdfMarkObjectUsed();
651
edisonn@google.com571c70b2013-07-10 17:09:50 +0000652 return fObjectType == kKeyword_PdfObjectType;
653 }
654
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000655 bool isKeyword(const char* keyword) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000656 SkPdfMarkObjectUsed();
657
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000658 if (!isKeyword()) {
659 return false;
660 }
661
662 if (strlen(keyword) != fStr.fBytes) {
663 return false;
664 }
665
666 if (strncmp(keyword, (const char*)fStr.fBuffer, fStr.fBytes) != 0) {
667 return false;
668 }
669
670 return true;
671 }
672
edisonn@google.com571c70b2013-07-10 17:09:50 +0000673 bool isName() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000674 SkPdfMarkObjectUsed();
675
edisonn@google.com571c70b2013-07-10 17:09:50 +0000676 return fObjectType == kName_PdfObjectType;
677 }
678
edisonn@google.com78b38b12013-07-15 18:20:58 +0000679 bool isName(const char* name) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000680 SkPdfMarkObjectUsed();
681
edisonn@google.com78b38b12013-07-15 18:20:58 +0000682 return fObjectType == kName_PdfObjectType && fStr.fBytes == strlen(name) && strncmp((const char*)fStr.fBuffer, name, fStr.fBytes) == 0;
683 }
684
edisonn@google.com571c70b2013-07-10 17:09:50 +0000685 bool isArray() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000686 SkPdfMarkObjectUsed();
687
edisonn@google.com571c70b2013-07-10 17:09:50 +0000688 return fObjectType == kArray_PdfObjectType;
689 }
690
691 bool isDate() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000692 SkPdfMarkObjectUsed();
693
edisonn@google.com571c70b2013-07-10 17:09:50 +0000694 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
695 }
696
697 bool isDictionary() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000698 SkPdfMarkObjectUsed();
699
edisonn@google.com571c70b2013-07-10 17:09:50 +0000700 return fObjectType == kDictionary_PdfObjectType;
701 }
702
703 bool isFunction() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000704 SkPdfMarkObjectUsed();
705
edisonn@google.com571c70b2013-07-10 17:09:50 +0000706 return false; // NYI
707 }
708
709 bool isRectangle() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000710 SkPdfMarkObjectUsed();
711
edisonn@google.com571c70b2013-07-10 17:09:50 +0000712 return fObjectType == kArray_PdfObjectType && fArray->count() == 4; // NYI + and elems are numbers
713 }
714
715 // TODO(edisonn): has stream .. or is stream ... TBD
716 bool hasStream() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000717 SkPdfMarkObjectUsed();
718
edisonn@google.com571c70b2013-07-10 17:09:50 +0000719 return isDictionary() && fStr.fBuffer != NULL;
720 }
721
722 // TODO(edisonn): has stream .. or is stream ... TBD
723 const SkPdfStream* getStream() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000724 SkPdfMarkObjectUsed();
725
edisonn@google.com571c70b2013-07-10 17:09:50 +0000726 return hasStream() ? (const SkPdfStream*)this : NULL;
727 }
728
729 SkPdfStream* getStream() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000730 SkPdfMarkObjectUsed();
731
edisonn@google.com571c70b2013-07-10 17:09:50 +0000732 return hasStream() ? (SkPdfStream*)this : NULL;
733 }
734
735 bool isAnyString() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000736 SkPdfMarkObjectUsed();
737
edisonn@google.com571c70b2013-07-10 17:09:50 +0000738 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
739 }
740
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000741 bool isHexString() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000742 SkPdfMarkObjectUsed();
743
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000744 return fObjectType == kHexString_PdfObjectType;
745 }
746
edisonn@google.com571c70b2013-07-10 17:09:50 +0000747 bool isMatrix() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000748 SkPdfMarkObjectUsed();
749
edisonn@google.com571c70b2013-07-10 17:09:50 +0000750 return fObjectType == kArray_PdfObjectType && fArray->count() == 6; // NYI + and elems are numbers
751 }
752
753 inline int64_t intValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000754 SkPdfMarkObjectUsed();
755
edisonn@google.com571c70b2013-07-10 17:09:50 +0000756 SkASSERT(fObjectType == kInteger_PdfObjectType);
757
758 if (fObjectType != kInteger_PdfObjectType) {
759 // TODO(edisonn): log err
760 return 0;
761 }
762 return fIntegerValue;
763 }
764private:
765 inline double realValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000766 SkPdfMarkObjectUsed();
767
edisonn@google.com571c70b2013-07-10 17:09:50 +0000768 SkASSERT(fObjectType == kReal_PdfObjectType);
769
770 if (fObjectType != kReal_PdfObjectType) {
771 // TODO(edisonn): log err
772 return 0;
773 }
774 return fRealValue;
775 }
776public:
777 inline double numberValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000778 SkPdfMarkObjectUsed();
779
edisonn@google.com571c70b2013-07-10 17:09:50 +0000780 SkASSERT(isNumber());
781
782 if (!isNumber()) {
783 // TODO(edisonn): log err
784 return 0;
785 }
786 return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue;
787 }
788
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000789 inline SkScalar scalarValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000790 SkPdfMarkObjectUsed();
791
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000792 SkASSERT(isNumber());
793
794 if (!isNumber()) {
795 // TODO(edisonn): log err
796 return SkIntToScalar(0);
797 }
798 return fObjectType == kReal_PdfObjectType ? SkDoubleToScalar(fRealValue) :
799 SkIntToScalar(fIntegerValue);
800 }
801
edisonn@google.com571c70b2013-07-10 17:09:50 +0000802 int referenceId() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000803 SkPdfMarkObjectUsed();
804
edisonn@google.com571c70b2013-07-10 17:09:50 +0000805 SkASSERT(fObjectType == kReference_PdfObjectType);
806 return fRef.fId;
807 }
808
809 int referenceGeneration() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000810 SkPdfMarkObjectUsed();
811
edisonn@google.com571c70b2013-07-10 17:09:50 +0000812 SkASSERT(fObjectType == kReference_PdfObjectType);
813 return fRef.fGen;
814 }
815
816 inline const char* nameValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000817 SkPdfMarkObjectUsed();
818
edisonn@google.com571c70b2013-07-10 17:09:50 +0000819 SkASSERT(fObjectType == kName_PdfObjectType);
820
821 if (fObjectType != kName_PdfObjectType) {
822 // TODO(edisonn): log err
823 return "";
824 }
825 return (const char*)fStr.fBuffer;
826 }
827
828 inline const char* stringValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000829 SkPdfMarkObjectUsed();
830
edisonn@google.com571c70b2013-07-10 17:09:50 +0000831 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
832
833 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
834 // TODO(edisonn): log err
835 return "";
836 }
837 return (const char*)fStr.fBuffer;
838 }
839
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000840 inline NotOwnedString strRef() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000841 SkPdfMarkObjectUsed();
842
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000843 switch (fObjectType) {
844 case kString_PdfObjectType:
845 case kHexString_PdfObjectType:
846 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000847 case kName_PdfObjectType:
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000848 return fStr;
849
850 default:
851 // TODO(edisonn): report/warning
852 return NotOwnedString();
853 }
854 }
855
edisonn@google.com571c70b2013-07-10 17:09:50 +0000856 // TODO(edisonn): nameValue2 and stringValue2 are used to make code generation easy,
857 // but it is not a performat way to do it, since it will create an extra copy
858 // remove these functions and make code generated faster
edisonn@google.com063d7072013-08-16 15:05:08 +0000859 inline SkString nameValue2() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000860 SkPdfMarkObjectUsed();
861
edisonn@google.com571c70b2013-07-10 17:09:50 +0000862 SkASSERT(fObjectType == kName_PdfObjectType);
863
864 if (fObjectType != kName_PdfObjectType) {
865 // TODO(edisonn): log err
edisonn@google.com063d7072013-08-16 15:05:08 +0000866 return SkString();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000867 }
edisonn@google.com063d7072013-08-16 15:05:08 +0000868 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000869 }
870
edisonn@google.com063d7072013-08-16 15:05:08 +0000871 inline SkString stringValue2() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000872 SkPdfMarkObjectUsed();
873
edisonn@google.com571c70b2013-07-10 17:09:50 +0000874 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
875
876 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
877 // TODO(edisonn): log err
edisonn@google.com063d7072013-08-16 15:05:08 +0000878 return SkString();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000879 }
edisonn@google.com063d7072013-08-16 15:05:08 +0000880 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000881 }
882
883 inline bool boolValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000884 SkPdfMarkObjectUsed();
885
edisonn@google.com571c70b2013-07-10 17:09:50 +0000886 SkASSERT(fObjectType == kBoolean_PdfObjectType);
887
edisonn@google.comf111a4b2013-07-31 18:22:36 +0000888 if (fObjectType != kBoolean_PdfObjectType) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000889 // TODO(edisonn): log err
890 return false;
891 }
892 return fBooleanValue;
893 }
894
895 SkRect rectangleValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000896 SkPdfMarkObjectUsed();
897
edisonn@google.com571c70b2013-07-10 17:09:50 +0000898 SkASSERT(isRectangle());
899 if (!isRectangle()) {
900 return SkRect::MakeEmpty();
901 }
902
903 double array[4];
904 for (int i = 0; i < 4; i++) {
905 // TODO(edisonn): version where we could resolve references?
edisonn@google.com3aa35552013-08-14 18:26:20 +0000906 const SkPdfNativeObject* elem = objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000907 if (elem == NULL || !elem->isNumber()) {
908 // TODO(edisonn): report error
909 return SkRect::MakeEmpty();
910 }
911 array[i] = elem->numberValue();
912 }
913
914 return SkRect::MakeLTRB(SkDoubleToScalar(array[0]),
915 SkDoubleToScalar(array[1]),
916 SkDoubleToScalar(array[2]),
917 SkDoubleToScalar(array[3]));
918 }
919
920 SkMatrix matrixValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000921 SkPdfMarkObjectUsed();
922
edisonn@google.com571c70b2013-07-10 17:09:50 +0000923 SkASSERT(isMatrix());
924 if (!isMatrix()) {
925 return SkMatrix::I();
926 }
927
928 double array[6];
929 for (int i = 0; i < 6; i++) {
930 // TODO(edisonn): version where we could resolve references?
edisonn@google.com3aa35552013-08-14 18:26:20 +0000931 const SkPdfNativeObject* elem = objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000932 if (elem == NULL || !elem->isNumber()) {
933 // TODO(edisonn): report error
934 return SkMatrix::I();
935 }
936 array[i] = elem->numberValue();
937 }
938
939 return SkMatrixFromPdfMatrix(array);
940 }
941
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000942 bool filterStream();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000943
944
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000945 bool GetFilteredStreamRef(unsigned char const** buffer, size_t* len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000946 SkPdfMarkObjectUsed();
947
edisonn@google.com571c70b2013-07-10 17:09:50 +0000948 // TODO(edisonn): add params that couls let the last filter in place if it is jpeg or png to fast load images
949 if (!hasStream()) {
950 return false;
951 }
952
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000953 filterStream();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000954
955 if (buffer) {
956 *buffer = fStr.fBuffer;
957 }
958
959 if (len) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000960 *len = fStr.fBytes >> 2; // last 2 bits
edisonn@google.com571c70b2013-07-10 17:09:50 +0000961 }
962
963 return true;
964 }
965
966 bool isStreamFiltered() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000967 SkPdfMarkObjectUsed();
968
edisonn@google.com571c70b2013-07-10 17:09:50 +0000969 return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit);
970 }
971
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000972 bool isStreamOwned() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000973 SkPdfMarkObjectUsed();
974
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000975 return hasStream() && ((fStr.fBytes & 2) == kOwnedStreamBit);
976 }
977
978 bool GetUnfilteredStreamRef(unsigned char const** buffer, size_t* len) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000979 SkPdfMarkObjectUsed();
980
edisonn@google.com571c70b2013-07-10 17:09:50 +0000981 if (isStreamFiltered()) {
982 return false;
983 }
984
985 if (!hasStream()) {
986 return false;
987 }
988
989 if (buffer) {
990 *buffer = fStr.fBuffer;
991 }
992
993 if (len) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000994 *len = fStr.fBytes >> 2; // remove last 2 bits
edisonn@google.com571c70b2013-07-10 17:09:50 +0000995 }
996
997 return true;
998 }
999
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001000 bool addStream(const unsigned char* buffer, size_t len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001001 //SkPdfMarkObjectUsed();
1002
edisonn@google.com571c70b2013-07-10 17:09:50 +00001003 SkASSERT(!hasStream());
1004 SkASSERT(isDictionary());
1005
1006 if (!isDictionary() || hasStream()) {
1007 return false;
1008 }
1009
1010 fStr.fBuffer = buffer;
1011 fStr.fBytes = (len << 2) + kUnfilteredStreamBit;
1012
1013 return true;
1014 }
1015
edisonn@google.com276fed92013-08-01 21:20:47 +00001016 static void appendSpaces(SkString* str, int level) {
edisonn@google.com9a43c182013-08-01 20:06:42 +00001017 for (int i = 0 ; i < level; i++) {
1018 str->append(" ");
1019 }
1020 }
1021
edisonn@google.com3aa35552013-08-14 18:26:20 +00001022 static void append(SkString* str, const char* data, size_t len, const char* prefix = "\\x") {
1023 for (unsigned int i = 0 ; i < len; i++) {
1024 if (data[i] == kNUL_PdfWhiteSpace) {
1025 str->append(prefix);
1026 str->append("00");
1027 } else if (data[i] == kHT_PdfWhiteSpace) {
1028 str->append(prefix);
1029 str->append("09");
1030 } else if (data[i] == kLF_PdfWhiteSpace) {
1031 str->append(prefix);
1032 str->append("0A");
1033 } else if (data[i] == kFF_PdfWhiteSpace) {
1034 str->append(prefix);
1035 str->append("0C");
1036 } else if (data[i] == kCR_PdfWhiteSpace) {
1037 str->append(prefix);
1038 str->append("0D");
1039 } else {
1040 str->append(data + i, 1);
1041 }
1042 }
1043 }
1044
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001045 SkString toString(int firstRowLevel = 0, int level = 0) {
edisonn@google.com571c70b2013-07-10 17:09:50 +00001046 SkString str;
edisonn@google.com9a43c182013-08-01 20:06:42 +00001047 appendSpaces(&str, firstRowLevel);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001048 switch (fObjectType) {
1049 case kInvalid_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001050 str.append("__Invalid");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001051 break;
1052
1053 case kBoolean_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001054 str.appendf("%s", fBooleanValue ? "true" : "false");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001055 break;
1056
1057 case kInteger_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001058 str.appendf("%i", (int)fIntegerValue);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001059 break;
1060
1061 case kReal_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001062 str.appendf("%f", fRealValue);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001063 break;
1064
1065 case kString_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001066 str.append("\"");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001067 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com9a43c182013-08-01 20:06:42 +00001068 str.append("\"");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001069 break;
1070
1071 case kHexString_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001072 str.append("<");
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001073 for (unsigned int i = 0 ; i < fStr.fBytes; i++) {
1074 str.appendf("%02x", (unsigned int)fStr.fBuffer[i]);
1075 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001076 str.append(">");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001077 break;
1078
1079 case kName_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001080 str.append("/");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001081 append(&str, (const char*)fStr.fBuffer, fStr.fBytes, "#");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001082 break;
1083
1084 case kKeyword_PdfObjectType:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001085 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001086 break;
1087
1088 case kArray_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001089 str.append("[\n");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001090 for (unsigned int i = 0; i < size(); i++) {
edisonn@google.com9a43c182013-08-01 20:06:42 +00001091 str.append(objAtAIndex(i)->toString(level + 1, level + 1));
1092 if (i < size() - 1) {
1093 str.append(",");
1094 }
1095 str.append("\n");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001096 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001097 appendSpaces(&str, level);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001098 str.append("]");
1099 break;
1100
edisonn@google.com9a43c182013-08-01 20:06:42 +00001101 case kDictionary_PdfObjectType: {
edisonn@google.com3aa35552013-08-14 18:26:20 +00001102 SkTDict<SkPdfNativeObject*>::Iter iter(*fMap);
1103 SkPdfNativeObject* obj = NULL;
edisonn@google.com9a43c182013-08-01 20:06:42 +00001104 const char* key = NULL;
1105 str.append("<<\n");
1106 while ((key = iter.next(&obj)) != NULL) {
1107 appendSpaces(&str, level + 2);
1108 str.appendf("/%s %s\n", key, obj->toString(0, level + strlen(key) + 4).c_str());
1109 }
1110 appendSpaces(&str, level);
1111 str.append(">>");
1112 if (hasStream()) {
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001113 const unsigned char* stream = NULL;
1114 size_t length = 0;
1115 if (GetFilteredStreamRef(&stream, &length)) {
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001116 str.append("stream\n");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001117 append(&str, (const char*)stream, length > 256 ? 256 : length);
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001118 str.append("\nendstream");
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001119 } else {
1120 str.append("stream STREAM_ERROR endstream");
1121 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001122 }
edisonn@google.com571c70b2013-07-10 17:09:50 +00001123 }
1124 break;
1125
1126 case kNull_PdfObjectType:
1127 str = "NULL";
1128 break;
1129
1130 case kReference_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001131 str.appendf("%i %i R", fRef.fId, fRef.fGen);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001132 break;
1133
1134 case kUndefined_PdfObjectType:
1135 str = "Undefined";
1136 break;
1137
1138 default:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001139 str = "Error";
edisonn@google.com571c70b2013-07-10 17:09:50 +00001140 break;
1141 }
1142
1143 return str;
1144 }
1145
1146private:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001147 static void makeStringCore(const unsigned char* start, SkPdfNativeObject* obj, ObjectType type) {
edisonn@google.com571c70b2013-07-10 17:09:50 +00001148 makeStringCore(start, strlen((const char*)start), obj, type);
1149 }
1150
edisonn@google.com3aa35552013-08-14 18:26:20 +00001151 static void makeStringCore(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj, ObjectType type) {
edisonn@google.com571c70b2013-07-10 17:09:50 +00001152 makeStringCore(start, end - start, obj, type);
1153 }
1154
edisonn@google.com3aa35552013-08-14 18:26:20 +00001155 static void makeStringCore(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj, ObjectType type) {
edisonn@google.com571c70b2013-07-10 17:09:50 +00001156 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
1157
1158 obj->fObjectType = type;
1159 obj->fStr.fBuffer = start;
1160 obj->fStr.fBytes = bytes;
1161 }
1162
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001163 bool applyFilter(const char* name);
1164 bool applyFlateDecodeFilter();
1165 bool applyDCTDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +00001166};
1167
edisonn@google.com3aa35552013-08-14 18:26:20 +00001168class SkPdfStream : public SkPdfNativeObject {};
1169class SkPdfArray : public SkPdfNativeObject {};
1170class SkPdfString : public SkPdfNativeObject {};
1171class SkPdfHexString : public SkPdfNativeObject {};
1172class SkPdfInteger : public SkPdfNativeObject {};
1173class SkPdfReal : public SkPdfNativeObject {};
1174class SkPdfNumber : public SkPdfNativeObject {};
edisonn@google.com571c70b2013-07-10 17:09:50 +00001175
edisonn@google.com3aa35552013-08-14 18:26:20 +00001176class SkPdfName : public SkPdfNativeObject {
1177 SkPdfName() : SkPdfNativeObject() {
1178 SkPdfNativeObject::makeName((const unsigned char*)"", this);
edisonn@google.com78b38b12013-07-15 18:20:58 +00001179 }
1180public:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001181 SkPdfName(char* name) : SkPdfNativeObject() {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001182 this->makeName((const unsigned char*)name, this);
edisonn@google.com78b38b12013-07-15 18:20:58 +00001183 }
1184};
1185
edisonn@google.comcf2cfa12013-08-21 16:31:37 +00001186#endif // SkPdfNativeObject