blob: 344d6c668de08d1071940cacabae7e522c03bca1 [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.combca421b2013-09-05 20:00:21 +0000106 // Keep this the last entries
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000107#ifdef PDF_TRACK_OBJECT_USAGE
108 mutable bool fUsed;
109#endif // PDF_TRACK_OBJECT_USAGE
110
edisonn@google.combca421b2013-09-05 20:00:21 +0000111#ifdef PDF_TRACK_STREAM_OFFSETS
edisonn@google.com571c70b2013-07-10 17:09:50 +0000112public:
edisonn@google.combca421b2013-09-05 20:00:21 +0000113 int fStreamId;
114 int fOffsetStart;
115 int fOffsetEnd;
116#endif // PDF_TRACK_STREAM_OFFSETS
117
118public:
119
120#ifdef PDF_TRACK_STREAM_OFFSETS
121 int streamId() const { return fStreamId; }
122 int offsetStart() const { return fOffsetStart; }
123 int offsetEnd() const { return fOffsetEnd; }
124#endif // PDF_TRACK_STREAM_OFFSETS
125
edisonn@google.com571c70b2013-07-10 17:09:50 +0000126
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000127 SkPdfNativeObject() : fInRendering(0)
128 , fObjectType(kInvalid_PdfObjectType)
129 , fMap(NULL)
130 , fData(NULL)
131 , fDataType(kEmpty_Data)
132#ifdef PDF_TRACK_OBJECT_USAGE
133 , fUsed(false)
134#endif // PDF_TRACK_OBJECT_USAGE
edisonn@google.combca421b2013-09-05 20:00:21 +0000135
136#ifdef PDF_TRACK_STREAM_OFFSETS
137 , fStreamId(-1)
138 , fOffsetStart(-1)
139 , fOffsetEnd(-1)
140#endif // PDF_TRACK_STREAM_OFFSETS
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000141 {}
edisonn@google.com571c70b2013-07-10 17:09:50 +0000142
edisonn@google.com063d7072013-08-16 15:05:08 +0000143 bool inRendering() const { return fInRendering != 0; }
144 void startRendering() {fInRendering = 1;}
145 void doneRendering() {fInRendering = 0;}
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000146
147 inline bool hasData(DataType type) {
148 return type == fDataType;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000149 }
150
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000151 inline void* data(DataType type) {
152 return type == fDataType ? fData : NULL;
153 }
154
155 inline void setData(void* data, DataType type) {
156 releaseData();
157 fDataType = type;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000158 fData = data;
159 }
160
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000161 void releaseData();
162
edisonn@google.com3aa35552013-08-14 18:26:20 +0000163// ~SkPdfNativeObject() {
edisonn@google.com222382b2013-07-10 22:33:10 +0000164// //reset(); must be called manually!
165// }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000166
167 void reset() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000168 SkPdfMarkObjectUnused();
169
edisonn@google.com571c70b2013-07-10 17:09:50 +0000170 switch (fObjectType) {
171 case kArray_PdfObjectType:
172 delete fArray;
173 break;
174
175 case kDictionary_PdfObjectType:
176 delete fMap;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000177 if (isStreamOwned()) {
178 delete[] fStr.fBuffer;
179 fStr.fBuffer = NULL;
180 fStr.fBytes = 0;
181 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000182 break;
183
184 default:
185 break;
186 }
187 fObjectType = kInvalid_PdfObjectType;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000188 releaseData();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000189 }
190
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000191 ObjectType type() {
192 SkPdfMarkObjectUsed();
193
194 return fObjectType;
195 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000196
197 const char* c_str() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000198 SkPdfMarkObjectUsed();
199
edisonn@google.com571c70b2013-07-10 17:09:50 +0000200 switch (fObjectType) {
201 case kString_PdfObjectType:
202 case kHexString_PdfObjectType:
203 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000204 case kName_PdfObjectType:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000205 return (const char*)fStr.fBuffer;
206
207 default:
208 // TODO(edisonn): report/warning
209 return NULL;
210 }
211 }
212
edisonn@google.come878e722013-07-29 19:10:58 +0000213 size_t lenstr() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000214 SkPdfMarkObjectUsed();
215
edisonn@google.com571c70b2013-07-10 17:09:50 +0000216 switch (fObjectType) {
217 case kString_PdfObjectType:
218 case kHexString_PdfObjectType:
219 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000220 case kName_PdfObjectType:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000221 return fStr.fBytes;
222
223 default:
224 // TODO(edisonn): report/warning
225 return 0;
226 }
227 }
228
229
230 // TODO(edisonn): NYI
231 SkPdfDate& dateValue() const {
232 static SkPdfDate nyi;
233 return nyi;
234 }
235
236 // TODO(edisonn): NYI
237 SkPdfFunction& functionValue() const {
238 static SkPdfFunction nyi;
239 return nyi;
240 }
241
242 // TODO(edisonn): NYI
243 SkPdfFileSpec& fileSpecValue() const {
244 static SkPdfFileSpec nyi;
245 return nyi;
246 }
247
248 // TODO(edisonn): NYI
249 SkPdfTree& treeValue() const {
250 static SkPdfTree nyi;
251 return nyi;
252 }
253
edisonn@google.combca421b2013-09-05 20:00:21 +0000254 static void makeBoolean(bool value, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
255 STORE_TRACK_PARAMETERS(obj);
256
edisonn@google.com571c70b2013-07-10 17:09:50 +0000257 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
258
259 obj->fObjectType = kBoolean_PdfObjectType;
260 obj->fBooleanValue = value;
261 }
262
edisonn@google.combca421b2013-09-05 20:00:21 +0000263 static SkPdfNativeObject makeBoolean(bool value GET_TRACK_PARAMETERS) {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000264 SkPdfNativeObject obj;
edisonn@google.combca421b2013-09-05 20:00:21 +0000265
266 STORE_TRACK_PARAMETERS(&obj);
267
edisonn@google.com571c70b2013-07-10 17:09:50 +0000268 obj.fObjectType = kBoolean_PdfObjectType;
269 obj.fBooleanValue = value;
270 return obj;
271 }
272
edisonn@google.combca421b2013-09-05 20:00:21 +0000273 static void makeInteger(int64_t value, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
274 STORE_TRACK_PARAMETERS(obj);
275
edisonn@google.com571c70b2013-07-10 17:09:50 +0000276 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
277
278 obj->fObjectType = kInteger_PdfObjectType;
279 obj->fIntegerValue = value;
280 }
281
edisonn@google.combca421b2013-09-05 20:00:21 +0000282 static void makeReal(double value, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
283 STORE_TRACK_PARAMETERS(obj);
284
edisonn@google.com571c70b2013-07-10 17:09:50 +0000285 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
286
287 obj->fObjectType = kReal_PdfObjectType;
288 obj->fRealValue = value;
289 }
290
edisonn@google.combca421b2013-09-05 20:00:21 +0000291 static void makeNull(SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
292 STORE_TRACK_PARAMETERS(obj);
293
edisonn@google.com571c70b2013-07-10 17:09:50 +0000294 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
295
296 obj->fObjectType = kNull_PdfObjectType;
297 }
298
edisonn@google.combca421b2013-09-05 20:00:21 +0000299 static SkPdfNativeObject makeNull(GET_TRACK_PARAMETERS0) {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000300 SkPdfNativeObject obj;
edisonn@google.combca421b2013-09-05 20:00:21 +0000301
302 STORE_TRACK_PARAMETERS(&obj);
303
edisonn@google.com571c70b2013-07-10 17:09:50 +0000304 obj.fObjectType = kNull_PdfObjectType;
305 return obj;
306 }
307
edisonn@google.com3aa35552013-08-14 18:26:20 +0000308 static SkPdfNativeObject kNull;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000309
edisonn@google.combca421b2013-09-05 20:00:21 +0000310 static void makeNumeric(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000311 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
312
313 // TODO(edisonn): NYI properly
314 // if has dot (impl), or exceeds max int, is real, otherwise is int
315 bool isInt = true;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000316 for (const unsigned char* current = start; current < end; current++) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000317 if (*current == '.') {
318 isInt = false;
319 break;
320 }
321 // TODO(edisonn): report parse issue with numbers like "24asdasd123"
322 }
323 if (isInt) {
edisonn@google.combca421b2013-09-05 20:00:21 +0000324 makeInteger(atol((const char*)start), obj PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000325 } else {
edisonn@google.combca421b2013-09-05 20:00:21 +0000326 makeReal(atof((const char*)start), obj PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000327 }
328 }
329
edisonn@google.combca421b2013-09-05 20:00:21 +0000330 static void makeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
331 STORE_TRACK_PARAMETERS(obj);
332
edisonn@google.com571c70b2013-07-10 17:09:50 +0000333 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
334
335 obj->fObjectType = kReference_PdfObjectType;
336 obj->fRef.fId = id;
337 obj->fRef.fGen = gen;
338 }
339
edisonn@google.combca421b2013-09-05 20:00:21 +0000340 static void resetAndMakeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
341 obj->reset();
342 makeReference(id, gen, obj PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000343 }
344
345
edisonn@google.combca421b2013-09-05 20:00:21 +0000346 static void makeString(const unsigned char* start, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
347 makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000348 }
349
edisonn@google.combca421b2013-09-05 20:00:21 +0000350 static void makeString(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
351 makeStringCore(start, end - start, obj, kString_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000352 }
353
edisonn@google.combca421b2013-09-05 20:00:21 +0000354 static void makeString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
355 makeStringCore(start, bytes, obj, kString_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000356 }
357
358
edisonn@google.combca421b2013-09-05 20:00:21 +0000359 static void makeHexString(const unsigned char* start, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
360 makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000361 }
362
edisonn@google.combca421b2013-09-05 20:00:21 +0000363 static void makeHexString(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
364 makeStringCore(start, end - start, obj, kHexString_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000365 }
366
edisonn@google.combca421b2013-09-05 20:00:21 +0000367 static void makeHexString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
368 makeStringCore(start, bytes, obj, kHexString_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000369 }
370
371
edisonn@google.combca421b2013-09-05 20:00:21 +0000372 static void makeName(const unsigned char* start, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
373 makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000374 }
375
edisonn@google.combca421b2013-09-05 20:00:21 +0000376 static void makeName(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
377 makeStringCore(start, end - start, obj, kName_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000378 }
379
edisonn@google.combca421b2013-09-05 20:00:21 +0000380 static void makeName(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
381 makeStringCore(start, bytes, obj, kName_PdfObjectType PUT_TRACK_PARAMETERS);
382 }
383
384
385 static void makeKeyword(const unsigned char* start, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
386 makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType PUT_TRACK_PARAMETERS);
387 }
388
389 static void makeKeyword(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
390 makeStringCore(start, end - start, obj, kKeyword_PdfObjectType PUT_TRACK_PARAMETERS);
391 }
392
393 static void makeKeyword(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
394 makeStringCore(start, bytes, obj, kKeyword_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000395 }
396
397
398
399 // TODO(edisonn): make the functions to return SkPdfArray, move these functions in SkPdfArray
edisonn@google.combca421b2013-09-05 20:00:21 +0000400 static void makeEmptyArray(SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
401 STORE_TRACK_PARAMETERS(obj);
402
edisonn@google.com571c70b2013-07-10 17:09:50 +0000403 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
404
405 obj->fObjectType = kArray_PdfObjectType;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000406 obj->fArray = new SkTDArray<SkPdfNativeObject*>();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000407 // return (SkPdfArray*)obj;
408 }
409
edisonn@google.com3aa35552013-08-14 18:26:20 +0000410 bool appendInArray(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000411 SkASSERT(fObjectType == kArray_PdfObjectType);
412 if (fObjectType != kArray_PdfObjectType) {
413 // TODO(edisonn): report err
414 return false;
415 }
416
417 fArray->push(obj);
418 return true;
419 }
420
421 size_t size() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000422 SkPdfMarkObjectUsed();
423
edisonn@google.com571c70b2013-07-10 17:09:50 +0000424 SkASSERT(fObjectType == kArray_PdfObjectType);
425
426 return fArray->count();
427 }
428
edisonn@google.com3aa35552013-08-14 18:26:20 +0000429 SkPdfNativeObject* objAtAIndex(int i) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000430 SkPdfMarkObjectUsed();
431
edisonn@google.com571c70b2013-07-10 17:09:50 +0000432 SkASSERT(fObjectType == kArray_PdfObjectType);
433
434 return (*fArray)[i];
435 }
436
edisonn@google.com3aa35552013-08-14 18:26:20 +0000437 SkPdfNativeObject* removeLastInArray() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000438 // SkPdfMarkObjectUsed();
439
edisonn@google.com571c70b2013-07-10 17:09:50 +0000440 SkASSERT(fObjectType == kArray_PdfObjectType);
441
edisonn@google.com3aa35552013-08-14 18:26:20 +0000442 SkPdfNativeObject* ret = NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000443 fArray->pop(&ret);
444
445 return ret;
446 }
447
448
edisonn@google.com3aa35552013-08-14 18:26:20 +0000449 const SkPdfNativeObject* objAtAIndex(int i) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000450 SkPdfMarkObjectUsed();
451
edisonn@google.com571c70b2013-07-10 17:09:50 +0000452 SkASSERT(fObjectType == kArray_PdfObjectType);
453
454 return (*fArray)[i];
455 }
456
edisonn@google.com3aa35552013-08-14 18:26:20 +0000457 SkPdfNativeObject* operator[](int i) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000458 SkASSERT(fObjectType == kArray_PdfObjectType);
459
460 return (*fArray)[i];
461 }
462
edisonn@google.com3aa35552013-08-14 18:26:20 +0000463 const SkPdfNativeObject* operator[](int i) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000464 SkPdfMarkObjectUsed();
465
edisonn@google.com571c70b2013-07-10 17:09:50 +0000466 SkASSERT(fObjectType == kArray_PdfObjectType);
467
468 return (*fArray)[i];
469 }
470
471
472 // TODO(edisonn): make the functions to return SkPdfDictionary, move these functions in SkPdfDictionary
edisonn@google.combca421b2013-09-05 20:00:21 +0000473 static void makeEmptyDictionary(SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
474 STORE_TRACK_PARAMETERS(obj);
475
edisonn@google.com571c70b2013-07-10 17:09:50 +0000476 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
477
478 obj->fObjectType = kDictionary_PdfObjectType;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000479 obj->fMap = new SkTDict<SkPdfNativeObject*>(1);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000480 obj->fStr.fBuffer = NULL;
481 obj->fStr.fBytes = 0;
482 }
483
484 // TODO(edisonn): get all the possible names from spec, and compute a hash function
485 // that would create no overlaps in the same dictionary
486 // or build a tree of chars that when followed goes to a unique id/index/hash
487 // TODO(edisonn): generate constants like kDictFoo, kNameDict_name
488 // which will be used in code
489 // add function SkPdfFastNameKey key(const char* key);
490 // TODO(edisonn): setting the same key twike, will make the value undefined!
edisonn@google.com3aa35552013-08-14 18:26:20 +0000491 bool set(const SkPdfNativeObject* key, SkPdfNativeObject* value) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000492 //SkPdfMarkObjectUsed();
493
edisonn@google.com571c70b2013-07-10 17:09:50 +0000494 SkASSERT(fObjectType == kDictionary_PdfObjectType);
495 SkASSERT(key->fObjectType == kName_PdfObjectType);
496
497 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
498 // TODO(edisonn): report err
499 return false;
500 }
501
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000502 //// we rewrite all delimiters and white spaces with '\0', so we expect the end of name to be '\0'
503 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
edisonn@google.com571c70b2013-07-10 17:09:50 +0000504
edisonn@google.comd761e322013-07-22 17:29:43 +0000505 return set(key->fStr.fBuffer, key->fStr.fBytes, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000506 }
507
edisonn@google.com3aa35552013-08-14 18:26:20 +0000508 bool set(const char* key, SkPdfNativeObject* value) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000509 //SkPdfMarkObjectUsed();
510
edisonn@google.comd761e322013-07-22 17:29:43 +0000511 return set((const unsigned char*)key, strlen(key), value);
512 }
513
edisonn@google.com3aa35552013-08-14 18:26:20 +0000514 bool set(const unsigned char* key, size_t len, SkPdfNativeObject* value) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000515 //SkPdfMarkObjectUsed();
516
edisonn@google.com571c70b2013-07-10 17:09:50 +0000517 SkASSERT(fObjectType == kDictionary_PdfObjectType);
518
519 if (fObjectType != kDictionary_PdfObjectType) {
520 // TODO(edisonn): report err
521 return false;
522 }
523
edisonn@google.comd761e322013-07-22 17:29:43 +0000524 return fMap->set((const char*)key, len, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000525 }
526
edisonn@google.com3aa35552013-08-14 18:26:20 +0000527 SkPdfNativeObject* get(const SkPdfNativeObject* key) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000528 SkPdfMarkObjectUsed();
529
edisonn@google.com571c70b2013-07-10 17:09:50 +0000530 SkASSERT(fObjectType == kDictionary_PdfObjectType);
531 SkASSERT(key->fObjectType == kName_PdfObjectType);
532
533 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
534 // TODO(edisonn): report err
edisonn@google.com3fc48262013-07-22 15:29:55 +0000535 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000536 }
537
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000538 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
edisonn@google.com571c70b2013-07-10 17:09:50 +0000539
edisonn@google.comd761e322013-07-22 17:29:43 +0000540 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000541 }
542
edisonn@google.com3aa35552013-08-14 18:26:20 +0000543 SkPdfNativeObject* get(const char* key) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000544 SkPdfMarkObjectUsed();
545
edisonn@google.comd761e322013-07-22 17:29:43 +0000546 return get((const unsigned char*)key, strlen(key));
547 }
548
edisonn@google.com3aa35552013-08-14 18:26:20 +0000549 SkPdfNativeObject* get(const unsigned char* key, size_t len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000550 SkPdfMarkObjectUsed();
551
edisonn@google.com571c70b2013-07-10 17:09:50 +0000552 SkASSERT(fObjectType == kDictionary_PdfObjectType);
553 SkASSERT(key);
554 if (fObjectType != kDictionary_PdfObjectType) {
555 // TODO(edisonn): report err
556 return NULL;
557 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000558 SkPdfNativeObject* ret = NULL;
edisonn@google.comd761e322013-07-22 17:29:43 +0000559 fMap->find((const char*)key, len, &ret);
edisonn@google.com9a43c182013-08-01 20:06:42 +0000560
561#ifdef PDF_TRACE
562 SkString _key;
563 _key.append((const char*)key, len);
564 printf("\nget(/%s) = %s\n", _key.c_str(), ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
565#endif
566
edisonn@google.com571c70b2013-07-10 17:09:50 +0000567 return ret;
568 }
569
edisonn@google.com3aa35552013-08-14 18:26:20 +0000570 const SkPdfNativeObject* get(const SkPdfNativeObject* key) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000571 SkPdfMarkObjectUsed();
572
edisonn@google.com571c70b2013-07-10 17:09:50 +0000573 SkASSERT(fObjectType == kDictionary_PdfObjectType);
574 SkASSERT(key->fObjectType == kName_PdfObjectType);
575
576 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
577 // TODO(edisonn): report err
edisonn@google.com3fc48262013-07-22 15:29:55 +0000578 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000579 }
580
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000581 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
edisonn@google.com571c70b2013-07-10 17:09:50 +0000582
edisonn@google.comd761e322013-07-22 17:29:43 +0000583 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000584 }
585
edisonn@google.com3aa35552013-08-14 18:26:20 +0000586 const SkPdfNativeObject* get(const char* key) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000587 SkPdfMarkObjectUsed();
588
edisonn@google.comd761e322013-07-22 17:29:43 +0000589 return get((const unsigned char*)key, strlen(key));
590 }
591
edisonn@google.com3aa35552013-08-14 18:26:20 +0000592 const SkPdfNativeObject* get(const unsigned char* key, size_t len) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000593 SkPdfMarkObjectUsed();
594
edisonn@google.com571c70b2013-07-10 17:09:50 +0000595 SkASSERT(fObjectType == kDictionary_PdfObjectType);
596 SkASSERT(key);
597 if (fObjectType != kDictionary_PdfObjectType) {
598 // TODO(edisonn): report err
599 return NULL;
600 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000601 SkPdfNativeObject* ret = NULL;
edisonn@google.comd761e322013-07-22 17:29:43 +0000602 fMap->find((const char*)key, len, &ret);
edisonn@google.com9a43c182013-08-01 20:06:42 +0000603
604#ifdef PDF_TRACE
605 SkString _key;
606 _key.append((const char*)key, len);
607 printf("\nget(/%s) = %s\n", _key.c_str(), ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
608#endif
609
edisonn@google.com571c70b2013-07-10 17:09:50 +0000610 return ret;
611 }
612
edisonn@google.com3aa35552013-08-14 18:26:20 +0000613 const SkPdfNativeObject* get(const char* key, const char* abr) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000614 SkPdfMarkObjectUsed();
615
edisonn@google.com3aa35552013-08-14 18:26:20 +0000616 const SkPdfNativeObject* ret = get(key);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000617 // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL
618 // make this distiontion in generator, and remove "" from condition
619 if (ret != NULL || abr == NULL || *abr == '\0') {
620 return ret;
621 }
622 return get(abr);
623 }
624
edisonn@google.com3aa35552013-08-14 18:26:20 +0000625 SkPdfNativeObject* get(const char* key, const char* abr) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000626 SkPdfMarkObjectUsed();
627
edisonn@google.com3aa35552013-08-14 18:26:20 +0000628 SkPdfNativeObject* ret = get(key);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000629 // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL
630 // make this distiontion in generator, and remove "" from condition
631 if (ret != NULL || abr == NULL || *abr == '\0') {
632 return ret;
633 }
634 return get(abr);
635 }
636
637 SkPdfDictionary* asDictionary() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000638 SkPdfMarkObjectUsed();
639
edisonn@google.com571c70b2013-07-10 17:09:50 +0000640 SkASSERT(isDictionary());
641 if (!isDictionary()) {
642 return NULL;
643 }
644 return (SkPdfDictionary*) this;
645 }
646
647 const SkPdfDictionary* asDictionary() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000648 SkPdfMarkObjectUsed();
649
edisonn@google.com571c70b2013-07-10 17:09:50 +0000650 SkASSERT(isDictionary());
651 if (!isDictionary()) {
652 return NULL;
653 }
654 return (SkPdfDictionary*) this;
655 }
656
657
658 bool isReference() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000659 SkPdfMarkObjectUsed();
660
edisonn@google.com571c70b2013-07-10 17:09:50 +0000661 return fObjectType == kReference_PdfObjectType;
662 }
663
664 bool isBoolean() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000665 SkPdfMarkObjectUsed();
666
edisonn@google.com571c70b2013-07-10 17:09:50 +0000667 return fObjectType == kBoolean_PdfObjectType;
668 }
669
670 bool isInteger() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000671 SkPdfMarkObjectUsed();
672
edisonn@google.com571c70b2013-07-10 17:09:50 +0000673 return fObjectType == kInteger_PdfObjectType;
674 }
675private:
676 bool isReal() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000677 SkPdfMarkObjectUsed();
678
edisonn@google.com571c70b2013-07-10 17:09:50 +0000679 return fObjectType == kReal_PdfObjectType;
680 }
681public:
682 bool isNumber() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000683 SkPdfMarkObjectUsed();
684
edisonn@google.com571c70b2013-07-10 17:09:50 +0000685 return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_PdfObjectType;
686 }
687
688 bool isKeywordReference() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000689 SkPdfMarkObjectUsed();
690
edisonn@google.com571c70b2013-07-10 17:09:50 +0000691 return fObjectType == kKeyword_PdfObjectType && fStr.fBytes == 1 && fStr.fBuffer[0] == 'R';
692 }
693
694 bool isKeyword() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000695 SkPdfMarkObjectUsed();
696
edisonn@google.com571c70b2013-07-10 17:09:50 +0000697 return fObjectType == kKeyword_PdfObjectType;
698 }
699
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000700 bool isKeyword(const char* keyword) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000701 SkPdfMarkObjectUsed();
702
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000703 if (!isKeyword()) {
704 return false;
705 }
706
707 if (strlen(keyword) != fStr.fBytes) {
708 return false;
709 }
710
711 if (strncmp(keyword, (const char*)fStr.fBuffer, fStr.fBytes) != 0) {
712 return false;
713 }
714
715 return true;
716 }
717
edisonn@google.com571c70b2013-07-10 17:09:50 +0000718 bool isName() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000719 SkPdfMarkObjectUsed();
720
edisonn@google.com571c70b2013-07-10 17:09:50 +0000721 return fObjectType == kName_PdfObjectType;
722 }
723
edisonn@google.com78b38b12013-07-15 18:20:58 +0000724 bool isName(const char* name) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000725 SkPdfMarkObjectUsed();
726
edisonn@google.com78b38b12013-07-15 18:20:58 +0000727 return fObjectType == kName_PdfObjectType && fStr.fBytes == strlen(name) && strncmp((const char*)fStr.fBuffer, name, fStr.fBytes) == 0;
728 }
729
edisonn@google.com571c70b2013-07-10 17:09:50 +0000730 bool isArray() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000731 SkPdfMarkObjectUsed();
732
edisonn@google.com571c70b2013-07-10 17:09:50 +0000733 return fObjectType == kArray_PdfObjectType;
734 }
735
736 bool isDate() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000737 SkPdfMarkObjectUsed();
738
edisonn@google.com571c70b2013-07-10 17:09:50 +0000739 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
740 }
741
742 bool isDictionary() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000743 SkPdfMarkObjectUsed();
744
edisonn@google.com571c70b2013-07-10 17:09:50 +0000745 return fObjectType == kDictionary_PdfObjectType;
746 }
747
748 bool isFunction() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000749 SkPdfMarkObjectUsed();
750
edisonn@google.com571c70b2013-07-10 17:09:50 +0000751 return false; // NYI
752 }
753
754 bool isRectangle() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000755 SkPdfMarkObjectUsed();
756
edisonn@google.com571c70b2013-07-10 17:09:50 +0000757 return fObjectType == kArray_PdfObjectType && fArray->count() == 4; // NYI + and elems are numbers
758 }
759
760 // TODO(edisonn): has stream .. or is stream ... TBD
761 bool hasStream() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000762 SkPdfMarkObjectUsed();
763
edisonn@google.com571c70b2013-07-10 17:09:50 +0000764 return isDictionary() && fStr.fBuffer != NULL;
765 }
766
767 // TODO(edisonn): has stream .. or is stream ... TBD
768 const SkPdfStream* getStream() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000769 SkPdfMarkObjectUsed();
770
edisonn@google.com571c70b2013-07-10 17:09:50 +0000771 return hasStream() ? (const SkPdfStream*)this : NULL;
772 }
773
774 SkPdfStream* getStream() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000775 SkPdfMarkObjectUsed();
776
edisonn@google.com571c70b2013-07-10 17:09:50 +0000777 return hasStream() ? (SkPdfStream*)this : NULL;
778 }
779
780 bool isAnyString() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000781 SkPdfMarkObjectUsed();
782
edisonn@google.com571c70b2013-07-10 17:09:50 +0000783 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
784 }
785
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000786 bool isHexString() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000787 SkPdfMarkObjectUsed();
788
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000789 return fObjectType == kHexString_PdfObjectType;
790 }
791
edisonn@google.com571c70b2013-07-10 17:09:50 +0000792 bool isMatrix() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000793 SkPdfMarkObjectUsed();
794
edisonn@google.com571c70b2013-07-10 17:09:50 +0000795 return fObjectType == kArray_PdfObjectType && fArray->count() == 6; // NYI + and elems are numbers
796 }
797
798 inline int64_t intValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000799 SkPdfMarkObjectUsed();
800
edisonn@google.com571c70b2013-07-10 17:09:50 +0000801 SkASSERT(fObjectType == kInteger_PdfObjectType);
802
803 if (fObjectType != kInteger_PdfObjectType) {
804 // TODO(edisonn): log err
805 return 0;
806 }
807 return fIntegerValue;
808 }
809private:
810 inline double realValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000811 SkPdfMarkObjectUsed();
812
edisonn@google.com571c70b2013-07-10 17:09:50 +0000813 SkASSERT(fObjectType == kReal_PdfObjectType);
814
815 if (fObjectType != kReal_PdfObjectType) {
816 // TODO(edisonn): log err
817 return 0;
818 }
819 return fRealValue;
820 }
821public:
822 inline double numberValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000823 SkPdfMarkObjectUsed();
824
edisonn@google.com571c70b2013-07-10 17:09:50 +0000825 SkASSERT(isNumber());
826
827 if (!isNumber()) {
828 // TODO(edisonn): log err
829 return 0;
830 }
831 return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue;
832 }
833
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000834 inline SkScalar scalarValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000835 SkPdfMarkObjectUsed();
836
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000837 SkASSERT(isNumber());
838
839 if (!isNumber()) {
840 // TODO(edisonn): log err
841 return SkIntToScalar(0);
842 }
843 return fObjectType == kReal_PdfObjectType ? SkDoubleToScalar(fRealValue) :
844 SkIntToScalar(fIntegerValue);
845 }
846
edisonn@google.com571c70b2013-07-10 17:09:50 +0000847 int referenceId() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000848 SkPdfMarkObjectUsed();
849
edisonn@google.com571c70b2013-07-10 17:09:50 +0000850 SkASSERT(fObjectType == kReference_PdfObjectType);
851 return fRef.fId;
852 }
853
854 int referenceGeneration() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000855 SkPdfMarkObjectUsed();
856
edisonn@google.com571c70b2013-07-10 17:09:50 +0000857 SkASSERT(fObjectType == kReference_PdfObjectType);
858 return fRef.fGen;
859 }
860
861 inline const char* nameValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000862 SkPdfMarkObjectUsed();
863
edisonn@google.com571c70b2013-07-10 17:09:50 +0000864 SkASSERT(fObjectType == kName_PdfObjectType);
865
866 if (fObjectType != kName_PdfObjectType) {
867 // TODO(edisonn): log err
868 return "";
869 }
870 return (const char*)fStr.fBuffer;
871 }
872
873 inline const char* stringValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000874 SkPdfMarkObjectUsed();
875
edisonn@google.com571c70b2013-07-10 17:09:50 +0000876 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
877
878 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
879 // TODO(edisonn): log err
880 return "";
881 }
882 return (const char*)fStr.fBuffer;
883 }
884
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000885 inline NotOwnedString strRef() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000886 SkPdfMarkObjectUsed();
887
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000888 switch (fObjectType) {
889 case kString_PdfObjectType:
890 case kHexString_PdfObjectType:
891 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000892 case kName_PdfObjectType:
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000893 return fStr;
894
895 default:
896 // TODO(edisonn): report/warning
897 return NotOwnedString();
898 }
899 }
900
edisonn@google.com571c70b2013-07-10 17:09:50 +0000901 // TODO(edisonn): nameValue2 and stringValue2 are used to make code generation easy,
902 // but it is not a performat way to do it, since it will create an extra copy
903 // remove these functions and make code generated faster
edisonn@google.com063d7072013-08-16 15:05:08 +0000904 inline SkString nameValue2() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000905 SkPdfMarkObjectUsed();
906
edisonn@google.com571c70b2013-07-10 17:09:50 +0000907 SkASSERT(fObjectType == kName_PdfObjectType);
908
909 if (fObjectType != kName_PdfObjectType) {
910 // TODO(edisonn): log err
edisonn@google.com063d7072013-08-16 15:05:08 +0000911 return SkString();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000912 }
edisonn@google.com063d7072013-08-16 15:05:08 +0000913 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000914 }
915
edisonn@google.com063d7072013-08-16 15:05:08 +0000916 inline SkString stringValue2() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000917 SkPdfMarkObjectUsed();
918
edisonn@google.com571c70b2013-07-10 17:09:50 +0000919 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
920
921 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
922 // TODO(edisonn): log err
edisonn@google.com063d7072013-08-16 15:05:08 +0000923 return SkString();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000924 }
edisonn@google.com063d7072013-08-16 15:05:08 +0000925 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000926 }
927
928 inline bool boolValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000929 SkPdfMarkObjectUsed();
930
edisonn@google.com571c70b2013-07-10 17:09:50 +0000931 SkASSERT(fObjectType == kBoolean_PdfObjectType);
932
edisonn@google.comf111a4b2013-07-31 18:22:36 +0000933 if (fObjectType != kBoolean_PdfObjectType) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000934 // TODO(edisonn): log err
935 return false;
936 }
937 return fBooleanValue;
938 }
939
940 SkRect rectangleValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000941 SkPdfMarkObjectUsed();
942
edisonn@google.com571c70b2013-07-10 17:09:50 +0000943 SkASSERT(isRectangle());
944 if (!isRectangle()) {
945 return SkRect::MakeEmpty();
946 }
947
948 double array[4];
949 for (int i = 0; i < 4; i++) {
950 // TODO(edisonn): version where we could resolve references?
edisonn@google.com3aa35552013-08-14 18:26:20 +0000951 const SkPdfNativeObject* elem = objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000952 if (elem == NULL || !elem->isNumber()) {
953 // TODO(edisonn): report error
954 return SkRect::MakeEmpty();
955 }
956 array[i] = elem->numberValue();
957 }
958
959 return SkRect::MakeLTRB(SkDoubleToScalar(array[0]),
960 SkDoubleToScalar(array[1]),
961 SkDoubleToScalar(array[2]),
962 SkDoubleToScalar(array[3]));
963 }
964
965 SkMatrix matrixValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000966 SkPdfMarkObjectUsed();
967
edisonn@google.com571c70b2013-07-10 17:09:50 +0000968 SkASSERT(isMatrix());
969 if (!isMatrix()) {
970 return SkMatrix::I();
971 }
972
973 double array[6];
974 for (int i = 0; i < 6; i++) {
975 // TODO(edisonn): version where we could resolve references?
edisonn@google.com3aa35552013-08-14 18:26:20 +0000976 const SkPdfNativeObject* elem = objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000977 if (elem == NULL || !elem->isNumber()) {
978 // TODO(edisonn): report error
979 return SkMatrix::I();
980 }
981 array[i] = elem->numberValue();
982 }
983
984 return SkMatrixFromPdfMatrix(array);
985 }
986
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000987 bool filterStream();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000988
989
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000990 bool GetFilteredStreamRef(unsigned char const** buffer, size_t* len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000991 SkPdfMarkObjectUsed();
992
edisonn@google.com571c70b2013-07-10 17:09:50 +0000993 // TODO(edisonn): add params that couls let the last filter in place if it is jpeg or png to fast load images
994 if (!hasStream()) {
995 return false;
996 }
997
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000998 filterStream();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000999
1000 if (buffer) {
1001 *buffer = fStr.fBuffer;
1002 }
1003
1004 if (len) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001005 *len = fStr.fBytes >> 2; // last 2 bits
edisonn@google.com571c70b2013-07-10 17:09:50 +00001006 }
1007
1008 return true;
1009 }
1010
1011 bool isStreamFiltered() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001012 SkPdfMarkObjectUsed();
1013
edisonn@google.com571c70b2013-07-10 17:09:50 +00001014 return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit);
1015 }
1016
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001017 bool isStreamOwned() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001018 SkPdfMarkObjectUsed();
1019
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001020 return hasStream() && ((fStr.fBytes & 2) == kOwnedStreamBit);
1021 }
1022
1023 bool GetUnfilteredStreamRef(unsigned char const** buffer, size_t* len) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001024 SkPdfMarkObjectUsed();
1025
edisonn@google.com571c70b2013-07-10 17:09:50 +00001026 if (isStreamFiltered()) {
1027 return false;
1028 }
1029
1030 if (!hasStream()) {
1031 return false;
1032 }
1033
1034 if (buffer) {
1035 *buffer = fStr.fBuffer;
1036 }
1037
1038 if (len) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001039 *len = fStr.fBytes >> 2; // remove last 2 bits
edisonn@google.com571c70b2013-07-10 17:09:50 +00001040 }
1041
1042 return true;
1043 }
1044
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001045 bool addStream(const unsigned char* buffer, size_t len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001046 //SkPdfMarkObjectUsed();
1047
edisonn@google.com571c70b2013-07-10 17:09:50 +00001048 SkASSERT(!hasStream());
1049 SkASSERT(isDictionary());
1050
1051 if (!isDictionary() || hasStream()) {
1052 return false;
1053 }
1054
1055 fStr.fBuffer = buffer;
1056 fStr.fBytes = (len << 2) + kUnfilteredStreamBit;
1057
1058 return true;
1059 }
1060
edisonn@google.com276fed92013-08-01 21:20:47 +00001061 static void appendSpaces(SkString* str, int level) {
edisonn@google.com9a43c182013-08-01 20:06:42 +00001062 for (int i = 0 ; i < level; i++) {
1063 str->append(" ");
1064 }
1065 }
1066
edisonn@google.com3aa35552013-08-14 18:26:20 +00001067 static void append(SkString* str, const char* data, size_t len, const char* prefix = "\\x") {
1068 for (unsigned int i = 0 ; i < len; i++) {
1069 if (data[i] == kNUL_PdfWhiteSpace) {
1070 str->append(prefix);
1071 str->append("00");
1072 } else if (data[i] == kHT_PdfWhiteSpace) {
1073 str->append(prefix);
1074 str->append("09");
1075 } else if (data[i] == kLF_PdfWhiteSpace) {
1076 str->append(prefix);
1077 str->append("0A");
1078 } else if (data[i] == kFF_PdfWhiteSpace) {
1079 str->append(prefix);
1080 str->append("0C");
1081 } else if (data[i] == kCR_PdfWhiteSpace) {
1082 str->append(prefix);
1083 str->append("0D");
1084 } else {
1085 str->append(data + i, 1);
1086 }
1087 }
1088 }
1089
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001090 SkString toString(int firstRowLevel = 0, int level = 0) {
edisonn@google.com571c70b2013-07-10 17:09:50 +00001091 SkString str;
edisonn@google.com9a43c182013-08-01 20:06:42 +00001092 appendSpaces(&str, firstRowLevel);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001093 switch (fObjectType) {
1094 case kInvalid_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001095 str.append("__Invalid");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001096 break;
1097
1098 case kBoolean_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001099 str.appendf("%s", fBooleanValue ? "true" : "false");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001100 break;
1101
1102 case kInteger_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001103 str.appendf("%i", (int)fIntegerValue);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001104 break;
1105
1106 case kReal_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001107 str.appendf("%f", fRealValue);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001108 break;
1109
1110 case kString_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001111 str.append("\"");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001112 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com9a43c182013-08-01 20:06:42 +00001113 str.append("\"");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001114 break;
1115
1116 case kHexString_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001117 str.append("<");
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001118 for (unsigned int i = 0 ; i < fStr.fBytes; i++) {
1119 str.appendf("%02x", (unsigned int)fStr.fBuffer[i]);
1120 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001121 str.append(">");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001122 break;
1123
1124 case kName_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001125 str.append("/");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001126 append(&str, (const char*)fStr.fBuffer, fStr.fBytes, "#");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001127 break;
1128
1129 case kKeyword_PdfObjectType:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001130 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001131 break;
1132
1133 case kArray_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001134 str.append("[\n");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001135 for (unsigned int i = 0; i < size(); i++) {
edisonn@google.com9a43c182013-08-01 20:06:42 +00001136 str.append(objAtAIndex(i)->toString(level + 1, level + 1));
1137 if (i < size() - 1) {
1138 str.append(",");
1139 }
1140 str.append("\n");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001141 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001142 appendSpaces(&str, level);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001143 str.append("]");
1144 break;
1145
edisonn@google.com9a43c182013-08-01 20:06:42 +00001146 case kDictionary_PdfObjectType: {
edisonn@google.com3aa35552013-08-14 18:26:20 +00001147 SkTDict<SkPdfNativeObject*>::Iter iter(*fMap);
1148 SkPdfNativeObject* obj = NULL;
edisonn@google.com9a43c182013-08-01 20:06:42 +00001149 const char* key = NULL;
1150 str.append("<<\n");
1151 while ((key = iter.next(&obj)) != NULL) {
1152 appendSpaces(&str, level + 2);
1153 str.appendf("/%s %s\n", key, obj->toString(0, level + strlen(key) + 4).c_str());
1154 }
1155 appendSpaces(&str, level);
1156 str.append(">>");
1157 if (hasStream()) {
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001158 const unsigned char* stream = NULL;
1159 size_t length = 0;
1160 if (GetFilteredStreamRef(&stream, &length)) {
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001161 str.append("stream\n");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001162 append(&str, (const char*)stream, length > 256 ? 256 : length);
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001163 str.append("\nendstream");
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001164 } else {
1165 str.append("stream STREAM_ERROR endstream");
1166 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001167 }
edisonn@google.com571c70b2013-07-10 17:09:50 +00001168 }
1169 break;
1170
1171 case kNull_PdfObjectType:
1172 str = "NULL";
1173 break;
1174
1175 case kReference_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001176 str.appendf("%i %i R", fRef.fId, fRef.fGen);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001177 break;
1178
1179 case kUndefined_PdfObjectType:
1180 str = "Undefined";
1181 break;
1182
1183 default:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001184 str = "Error";
edisonn@google.com571c70b2013-07-10 17:09:50 +00001185 break;
1186 }
1187
1188 return str;
1189 }
1190
1191private:
edisonn@google.combca421b2013-09-05 20:00:21 +00001192 static void makeStringCore(const unsigned char* start, SkPdfNativeObject* obj, ObjectType type GET_TRACK_PARAMETERS) {
1193 makeStringCore(start, strlen((const char*)start), obj, type PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001194 }
1195
edisonn@google.combca421b2013-09-05 20:00:21 +00001196 static void makeStringCore(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj, ObjectType type GET_TRACK_PARAMETERS) {
1197 makeStringCore(start, end - start, obj, type PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001198 }
1199
edisonn@google.combca421b2013-09-05 20:00:21 +00001200 static void makeStringCore(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj, ObjectType type GET_TRACK_PARAMETERS) {
1201 STORE_TRACK_PARAMETERS(obj);
1202
edisonn@google.com571c70b2013-07-10 17:09:50 +00001203 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
1204
1205 obj->fObjectType = type;
1206 obj->fStr.fBuffer = start;
1207 obj->fStr.fBytes = bytes;
1208 }
1209
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001210 bool applyFilter(const char* name);
1211 bool applyFlateDecodeFilter();
1212 bool applyDCTDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +00001213};
1214
edisonn@google.com3aa35552013-08-14 18:26:20 +00001215class SkPdfStream : public SkPdfNativeObject {};
1216class SkPdfArray : public SkPdfNativeObject {};
1217class SkPdfString : public SkPdfNativeObject {};
1218class SkPdfHexString : public SkPdfNativeObject {};
1219class SkPdfInteger : public SkPdfNativeObject {};
1220class SkPdfReal : public SkPdfNativeObject {};
1221class SkPdfNumber : public SkPdfNativeObject {};
edisonn@google.com571c70b2013-07-10 17:09:50 +00001222
edisonn@google.com3aa35552013-08-14 18:26:20 +00001223class SkPdfName : public SkPdfNativeObject {
1224 SkPdfName() : SkPdfNativeObject() {
edisonn@google.combca421b2013-09-05 20:00:21 +00001225 SkPdfNativeObject::makeName((const unsigned char*)"", this PUT_TRACK_PARAMETERS_SRC);
edisonn@google.com78b38b12013-07-15 18:20:58 +00001226 }
1227public:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001228 SkPdfName(char* name) : SkPdfNativeObject() {
edisonn@google.combca421b2013-09-05 20:00:21 +00001229 this->makeName((const unsigned char*)name, this PUT_TRACK_PARAMETERS_SRC);
edisonn@google.com78b38b12013-07-15 18:20:58 +00001230 }
1231};
1232
edisonn@google.comcf2cfa12013-08-21 16:31:37 +00001233#endif // SkPdfNativeObject