blob: 94c0547c2269425dccec44c5ba340b58c79536ea [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 {
edisonn@google.comaf54a512013-09-13 19:33:42 +000041 // The type will have only one of these values, but for error reporting, we make it an enum
42 // so it can easily report that something was expected to be one of a few types
43 kInvalid_PdfObjectType = 1 << 1,
edisonn@google.com571c70b2013-07-10 17:09:50 +000044
edisonn@google.comaf54a512013-09-13 19:33:42 +000045 kBoolean_PdfObjectType = 1 << 2,
46 kInteger_PdfObjectType = 1 << 3,
47 kReal_PdfObjectType = 1 << 4,
48 _kNumber_PdfObjectType = kInteger_PdfObjectType | kReal_PdfObjectType,
49 kString_PdfObjectType = 1 << 5,
50 kHexString_PdfObjectType = 1 << 6,
51 _kAnyString_PdfObjectType = kString_PdfObjectType | kHexString_PdfObjectType,
52 kName_PdfObjectType = 1 << 7,
53 kKeyword_PdfObjectType = 1 << 8,
54 _kStream_PdfObjectType = 1 << 9, // attached to a Dictionary, do not use
55 kArray_PdfObjectType = 1 << 10,
56 kDictionary_PdfObjectType = 1 << 11,
57 kNull_PdfObjectType = 1 << 12,
edisonn@google.com571c70b2013-07-10 17:09:50 +000058
59 // TODO(edisonn): after the pdf has been loaded completely, resolve all references
60 // try the same thing with delayed loaded ...
edisonn@google.comaf54a512013-09-13 19:33:42 +000061 kReference_PdfObjectType = 1 << 13,
edisonn@google.com571c70b2013-07-10 17:09:50 +000062
edisonn@google.comaf54a512013-09-13 19:33:42 +000063 kUndefined_PdfObjectType = 1 << 14, // per 1.4 spec, if the same key appear twice in the dictionary, the value is undefined
64
65 _kObject_PdfObjectType = -1,
edisonn@google.com571c70b2013-07-10 17:09:50 +000066 };
67
edisonn@google.comb0145ce2013-08-05 16:23:23 +000068 enum DataType {
69 kEmpty_Data,
70 kFont_Data,
71 kBitmap_Data,
72 };
73
edisonn@google.com571c70b2013-07-10 17:09:50 +000074private:
edisonn@google.com063d7072013-08-16 15:05:08 +000075 // TODO(edisonn): assert reset operations while in rendering!
76 uint32_t fInRendering : 1;
77 uint32_t fUnused : 31;
78
79
edisonn@google.com571c70b2013-07-10 17:09:50 +000080 struct Reference {
81 unsigned int fId;
82 unsigned int fGen;
83 };
84
85 // TODO(edisonn): add stream start, stream end, where stream is weither the file
86 // or decoded/filtered pdf stream
87
88 // TODO(edisonn): add warning/report per object
89 // TODO(edisonn): add flag fUsed, to be used once the parsing is complete,
90 // so we could show what parts have been proccessed, ignored, or generated errors
91
92 ObjectType fObjectType;
93
94 union {
95 bool fBooleanValue;
96 int64_t fIntegerValue;
97 // TODO(edisonn): double, float? typedefed
98 double fRealValue;
99 NotOwnedString fStr;
100
101 // 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 +0000102 SkTDArray<SkPdfNativeObject*>* fArray;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000103 Reference fRef;
104 };
edisonn@google.com3aa35552013-08-14 18:26:20 +0000105 SkTDict<SkPdfNativeObject*>* fMap;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000106
107 // TODO(edisonn): rename data with cache
edisonn@google.com571c70b2013-07-10 17:09:50 +0000108 void* fData;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000109 DataType fDataType;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000110
111
edisonn@google.combca421b2013-09-05 20:00:21 +0000112 // Keep this the last entries
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000113#ifdef PDF_TRACK_OBJECT_USAGE
114 mutable bool fUsed;
115#endif // PDF_TRACK_OBJECT_USAGE
116
edisonn@google.combca421b2013-09-05 20:00:21 +0000117#ifdef PDF_TRACK_STREAM_OFFSETS
edisonn@google.com571c70b2013-07-10 17:09:50 +0000118public:
edisonn@google.combca421b2013-09-05 20:00:21 +0000119 int fStreamId;
120 int fOffsetStart;
121 int fOffsetEnd;
122#endif // PDF_TRACK_STREAM_OFFSETS
123
124public:
125
126#ifdef PDF_TRACK_STREAM_OFFSETS
127 int streamId() const { return fStreamId; }
128 int offsetStart() const { return fOffsetStart; }
129 int offsetEnd() const { return fOffsetEnd; }
130#endif // PDF_TRACK_STREAM_OFFSETS
131
edisonn@google.com571c70b2013-07-10 17:09:50 +0000132
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000133 SkPdfNativeObject() : fInRendering(0)
134 , fObjectType(kInvalid_PdfObjectType)
135 , fMap(NULL)
136 , fData(NULL)
137 , fDataType(kEmpty_Data)
138#ifdef PDF_TRACK_OBJECT_USAGE
139 , fUsed(false)
140#endif // PDF_TRACK_OBJECT_USAGE
edisonn@google.combca421b2013-09-05 20:00:21 +0000141
142#ifdef PDF_TRACK_STREAM_OFFSETS
143 , fStreamId(-1)
144 , fOffsetStart(-1)
145 , fOffsetEnd(-1)
146#endif // PDF_TRACK_STREAM_OFFSETS
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000147 {}
edisonn@google.com571c70b2013-07-10 17:09:50 +0000148
edisonn@google.com063d7072013-08-16 15:05:08 +0000149 bool inRendering() const { return fInRendering != 0; }
150 void startRendering() {fInRendering = 1;}
151 void doneRendering() {fInRendering = 0;}
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000152
153 inline bool hasData(DataType type) {
154 return type == fDataType;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000155 }
156
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000157 inline void* data(DataType type) {
158 return type == fDataType ? fData : NULL;
159 }
160
161 inline void setData(void* data, DataType type) {
162 releaseData();
163 fDataType = type;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000164 fData = data;
165 }
166
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000167 void releaseData();
168
edisonn@google.com3aa35552013-08-14 18:26:20 +0000169// ~SkPdfNativeObject() {
edisonn@google.com222382b2013-07-10 22:33:10 +0000170// //reset(); must be called manually!
171// }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000172
173 void reset() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000174 SkPdfMarkObjectUnused();
175
edisonn@google.com571c70b2013-07-10 17:09:50 +0000176 switch (fObjectType) {
177 case kArray_PdfObjectType:
178 delete fArray;
179 break;
180
181 case kDictionary_PdfObjectType:
182 delete fMap;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000183 if (isStreamOwned()) {
184 delete[] fStr.fBuffer;
185 fStr.fBuffer = NULL;
186 fStr.fBytes = 0;
187 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000188 break;
189
190 default:
191 break;
192 }
193 fObjectType = kInvalid_PdfObjectType;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000194 releaseData();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000195 }
196
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000197 ObjectType type() {
198 SkPdfMarkObjectUsed();
199
200 return fObjectType;
201 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000202
203 const char* c_str() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000204 SkPdfMarkObjectUsed();
205
edisonn@google.com571c70b2013-07-10 17:09:50 +0000206 switch (fObjectType) {
207 case kString_PdfObjectType:
208 case kHexString_PdfObjectType:
209 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000210 case kName_PdfObjectType:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000211 return (const char*)fStr.fBuffer;
212
213 default:
214 // TODO(edisonn): report/warning
215 return NULL;
216 }
217 }
218
edisonn@google.come878e722013-07-29 19:10:58 +0000219 size_t lenstr() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000220 SkPdfMarkObjectUsed();
221
edisonn@google.com571c70b2013-07-10 17:09:50 +0000222 switch (fObjectType) {
223 case kString_PdfObjectType:
224 case kHexString_PdfObjectType:
225 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000226 case kName_PdfObjectType:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000227 return fStr.fBytes;
228
229 default:
230 // TODO(edisonn): report/warning
231 return 0;
232 }
233 }
234
235
236 // TODO(edisonn): NYI
237 SkPdfDate& dateValue() const {
238 static SkPdfDate nyi;
239 return nyi;
240 }
241
242 // TODO(edisonn): NYI
243 SkPdfFunction& functionValue() const {
244 static SkPdfFunction nyi;
245 return nyi;
246 }
247
248 // TODO(edisonn): NYI
249 SkPdfFileSpec& fileSpecValue() const {
250 static SkPdfFileSpec nyi;
251 return nyi;
252 }
253
254 // TODO(edisonn): NYI
255 SkPdfTree& treeValue() const {
256 static SkPdfTree nyi;
257 return nyi;
258 }
259
edisonn@google.combca421b2013-09-05 20:00:21 +0000260 static void makeBoolean(bool value, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
261 STORE_TRACK_PARAMETERS(obj);
262
edisonn@google.com571c70b2013-07-10 17:09:50 +0000263 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
264
265 obj->fObjectType = kBoolean_PdfObjectType;
266 obj->fBooleanValue = value;
267 }
268
edisonn@google.combca421b2013-09-05 20:00:21 +0000269 static SkPdfNativeObject makeBoolean(bool value GET_TRACK_PARAMETERS) {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000270 SkPdfNativeObject obj;
edisonn@google.combca421b2013-09-05 20:00:21 +0000271
272 STORE_TRACK_PARAMETERS(&obj);
273
edisonn@google.com571c70b2013-07-10 17:09:50 +0000274 obj.fObjectType = kBoolean_PdfObjectType;
275 obj.fBooleanValue = value;
276 return obj;
277 }
278
edisonn@google.combca421b2013-09-05 20:00:21 +0000279 static void makeInteger(int64_t value, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
280 STORE_TRACK_PARAMETERS(obj);
281
edisonn@google.com571c70b2013-07-10 17:09:50 +0000282 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
283
284 obj->fObjectType = kInteger_PdfObjectType;
285 obj->fIntegerValue = value;
286 }
287
edisonn@google.combca421b2013-09-05 20:00:21 +0000288 static void makeReal(double value, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
289 STORE_TRACK_PARAMETERS(obj);
290
edisonn@google.com571c70b2013-07-10 17:09:50 +0000291 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
292
293 obj->fObjectType = kReal_PdfObjectType;
294 obj->fRealValue = value;
295 }
296
edisonn@google.combca421b2013-09-05 20:00:21 +0000297 static void makeNull(SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
298 STORE_TRACK_PARAMETERS(obj);
299
edisonn@google.com571c70b2013-07-10 17:09:50 +0000300 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
301
302 obj->fObjectType = kNull_PdfObjectType;
303 }
304
edisonn@google.combca421b2013-09-05 20:00:21 +0000305 static SkPdfNativeObject makeNull(GET_TRACK_PARAMETERS0) {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000306 SkPdfNativeObject obj;
edisonn@google.combca421b2013-09-05 20:00:21 +0000307
308 STORE_TRACK_PARAMETERS(&obj);
309
edisonn@google.com571c70b2013-07-10 17:09:50 +0000310 obj.fObjectType = kNull_PdfObjectType;
311 return obj;
312 }
313
edisonn@google.com3aa35552013-08-14 18:26:20 +0000314 static SkPdfNativeObject kNull;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000315
edisonn@google.combca421b2013-09-05 20:00:21 +0000316 static void makeNumeric(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000317 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
318
319 // TODO(edisonn): NYI properly
320 // if has dot (impl), or exceeds max int, is real, otherwise is int
321 bool isInt = true;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000322 for (const unsigned char* current = start; current < end; current++) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000323 if (*current == '.') {
324 isInt = false;
325 break;
326 }
327 // TODO(edisonn): report parse issue with numbers like "24asdasd123"
328 }
329 if (isInt) {
edisonn@google.combca421b2013-09-05 20:00:21 +0000330 makeInteger(atol((const char*)start), obj PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000331 } else {
edisonn@google.combca421b2013-09-05 20:00:21 +0000332 makeReal(atof((const char*)start), obj PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000333 }
334 }
335
edisonn@google.combca421b2013-09-05 20:00:21 +0000336 static void makeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
337 STORE_TRACK_PARAMETERS(obj);
338
edisonn@google.com571c70b2013-07-10 17:09:50 +0000339 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
340
341 obj->fObjectType = kReference_PdfObjectType;
342 obj->fRef.fId = id;
343 obj->fRef.fGen = gen;
344 }
345
edisonn@google.combca421b2013-09-05 20:00:21 +0000346 static void resetAndMakeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
347 obj->reset();
348 makeReference(id, gen, obj PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000349 }
350
351
edisonn@google.combca421b2013-09-05 20:00:21 +0000352 static void makeString(const unsigned char* start, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
353 makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000354 }
355
edisonn@google.combca421b2013-09-05 20:00:21 +0000356 static void makeString(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
357 makeStringCore(start, end - start, obj, kString_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000358 }
359
edisonn@google.combca421b2013-09-05 20:00:21 +0000360 static void makeString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
361 makeStringCore(start, bytes, obj, kString_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000362 }
363
364
edisonn@google.combca421b2013-09-05 20:00:21 +0000365 static void makeHexString(const unsigned char* start, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
366 makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000367 }
368
edisonn@google.combca421b2013-09-05 20:00:21 +0000369 static void makeHexString(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
370 makeStringCore(start, end - start, obj, kHexString_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000371 }
372
edisonn@google.combca421b2013-09-05 20:00:21 +0000373 static void makeHexString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
374 makeStringCore(start, bytes, obj, kHexString_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000375 }
376
377
edisonn@google.combca421b2013-09-05 20:00:21 +0000378 static void makeName(const unsigned char* start, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
379 makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000380 }
381
edisonn@google.combca421b2013-09-05 20:00:21 +0000382 static void makeName(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
383 makeStringCore(start, end - start, obj, kName_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000384 }
385
edisonn@google.combca421b2013-09-05 20:00:21 +0000386 static void makeName(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
387 makeStringCore(start, bytes, obj, kName_PdfObjectType PUT_TRACK_PARAMETERS);
388 }
389
390
391 static void makeKeyword(const unsigned char* start, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
392 makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType PUT_TRACK_PARAMETERS);
393 }
394
395 static void makeKeyword(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
396 makeStringCore(start, end - start, obj, kKeyword_PdfObjectType PUT_TRACK_PARAMETERS);
397 }
398
399 static void makeKeyword(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
400 makeStringCore(start, bytes, obj, kKeyword_PdfObjectType PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000401 }
402
403
404
405 // TODO(edisonn): make the functions to return SkPdfArray, move these functions in SkPdfArray
edisonn@google.combca421b2013-09-05 20:00:21 +0000406 static void makeEmptyArray(SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
407 STORE_TRACK_PARAMETERS(obj);
408
edisonn@google.com571c70b2013-07-10 17:09:50 +0000409 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
410
411 obj->fObjectType = kArray_PdfObjectType;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000412 obj->fArray = new SkTDArray<SkPdfNativeObject*>();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000413 // return (SkPdfArray*)obj;
414 }
415
edisonn@google.com3aa35552013-08-14 18:26:20 +0000416 bool appendInArray(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000417 SkASSERT(fObjectType == kArray_PdfObjectType);
418 if (fObjectType != kArray_PdfObjectType) {
419 // TODO(edisonn): report err
420 return false;
421 }
422
423 fArray->push(obj);
424 return true;
425 }
426
427 size_t size() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000428 SkPdfMarkObjectUsed();
429
edisonn@google.com571c70b2013-07-10 17:09:50 +0000430 SkASSERT(fObjectType == kArray_PdfObjectType);
431
432 return fArray->count();
433 }
434
edisonn@google.com3aa35552013-08-14 18:26:20 +0000435 SkPdfNativeObject* objAtAIndex(int i) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000436 SkPdfMarkObjectUsed();
437
edisonn@google.com571c70b2013-07-10 17:09:50 +0000438 SkASSERT(fObjectType == kArray_PdfObjectType);
439
440 return (*fArray)[i];
441 }
442
edisonn@google.com3aa35552013-08-14 18:26:20 +0000443 SkPdfNativeObject* removeLastInArray() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000444 // SkPdfMarkObjectUsed();
445
edisonn@google.com571c70b2013-07-10 17:09:50 +0000446 SkASSERT(fObjectType == kArray_PdfObjectType);
447
edisonn@google.com3aa35552013-08-14 18:26:20 +0000448 SkPdfNativeObject* ret = NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000449 fArray->pop(&ret);
450
451 return ret;
452 }
453
454
edisonn@google.com3aa35552013-08-14 18:26:20 +0000455 const SkPdfNativeObject* objAtAIndex(int i) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000456 SkPdfMarkObjectUsed();
457
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 SkPdfNativeObject* operator[](int i) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000464 SkASSERT(fObjectType == kArray_PdfObjectType);
465
466 return (*fArray)[i];
467 }
468
edisonn@google.com3aa35552013-08-14 18:26:20 +0000469 const SkPdfNativeObject* operator[](int i) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000470 SkPdfMarkObjectUsed();
471
edisonn@google.com571c70b2013-07-10 17:09:50 +0000472 SkASSERT(fObjectType == kArray_PdfObjectType);
473
474 return (*fArray)[i];
475 }
476
477
478 // TODO(edisonn): make the functions to return SkPdfDictionary, move these functions in SkPdfDictionary
edisonn@google.combca421b2013-09-05 20:00:21 +0000479 static void makeEmptyDictionary(SkPdfNativeObject* obj GET_TRACK_PARAMETERS) {
480 STORE_TRACK_PARAMETERS(obj);
481
edisonn@google.com571c70b2013-07-10 17:09:50 +0000482 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
483
484 obj->fObjectType = kDictionary_PdfObjectType;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000485 obj->fMap = new SkTDict<SkPdfNativeObject*>(1);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000486 obj->fStr.fBuffer = NULL;
487 obj->fStr.fBytes = 0;
488 }
489
490 // TODO(edisonn): get all the possible names from spec, and compute a hash function
491 // that would create no overlaps in the same dictionary
492 // or build a tree of chars that when followed goes to a unique id/index/hash
493 // TODO(edisonn): generate constants like kDictFoo, kNameDict_name
494 // which will be used in code
495 // add function SkPdfFastNameKey key(const char* key);
496 // TODO(edisonn): setting the same key twike, will make the value undefined!
edisonn@google.com3aa35552013-08-14 18:26:20 +0000497 bool set(const SkPdfNativeObject* key, SkPdfNativeObject* value) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000498 //SkPdfMarkObjectUsed();
499
edisonn@google.com571c70b2013-07-10 17:09:50 +0000500 SkASSERT(fObjectType == kDictionary_PdfObjectType);
501 SkASSERT(key->fObjectType == kName_PdfObjectType);
502
503 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
504 // TODO(edisonn): report err
505 return false;
506 }
507
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000508 //// we rewrite all delimiters and white spaces with '\0', so we expect the end of name to be '\0'
509 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
edisonn@google.com571c70b2013-07-10 17:09:50 +0000510
edisonn@google.comd761e322013-07-22 17:29:43 +0000511 return set(key->fStr.fBuffer, key->fStr.fBytes, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000512 }
513
edisonn@google.com3aa35552013-08-14 18:26:20 +0000514 bool set(const char* key, SkPdfNativeObject* value) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000515 //SkPdfMarkObjectUsed();
516
edisonn@google.comd761e322013-07-22 17:29:43 +0000517 return set((const unsigned char*)key, strlen(key), value);
518 }
519
edisonn@google.com3aa35552013-08-14 18:26:20 +0000520 bool set(const unsigned char* key, size_t len, SkPdfNativeObject* value) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000521 //SkPdfMarkObjectUsed();
522
edisonn@google.com571c70b2013-07-10 17:09:50 +0000523 SkASSERT(fObjectType == kDictionary_PdfObjectType);
524
525 if (fObjectType != kDictionary_PdfObjectType) {
526 // TODO(edisonn): report err
527 return false;
528 }
529
edisonn@google.comd761e322013-07-22 17:29:43 +0000530 return fMap->set((const char*)key, len, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000531 }
532
edisonn@google.com3aa35552013-08-14 18:26:20 +0000533 SkPdfNativeObject* get(const SkPdfNativeObject* key) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000534 SkPdfMarkObjectUsed();
535
edisonn@google.com571c70b2013-07-10 17:09:50 +0000536 SkASSERT(fObjectType == kDictionary_PdfObjectType);
537 SkASSERT(key->fObjectType == kName_PdfObjectType);
538
539 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
540 // TODO(edisonn): report err
edisonn@google.com3fc48262013-07-22 15:29:55 +0000541 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000542 }
543
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000544 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
edisonn@google.com571c70b2013-07-10 17:09:50 +0000545
edisonn@google.comd761e322013-07-22 17:29:43 +0000546 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000547 }
548
edisonn@google.com3aa35552013-08-14 18:26:20 +0000549 SkPdfNativeObject* get(const char* key) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000550 SkPdfMarkObjectUsed();
551
edisonn@google.comd761e322013-07-22 17:29:43 +0000552 return get((const unsigned char*)key, strlen(key));
553 }
554
edisonn@google.com3aa35552013-08-14 18:26:20 +0000555 SkPdfNativeObject* get(const unsigned char* key, size_t len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000556 SkPdfMarkObjectUsed();
557
edisonn@google.com571c70b2013-07-10 17:09:50 +0000558 SkASSERT(fObjectType == kDictionary_PdfObjectType);
559 SkASSERT(key);
560 if (fObjectType != kDictionary_PdfObjectType) {
561 // TODO(edisonn): report err
562 return NULL;
563 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000564 SkPdfNativeObject* ret = NULL;
edisonn@google.comd761e322013-07-22 17:29:43 +0000565 fMap->find((const char*)key, len, &ret);
edisonn@google.com9a43c182013-08-01 20:06:42 +0000566
567#ifdef PDF_TRACE
568 SkString _key;
569 _key.append((const char*)key, len);
570 printf("\nget(/%s) = %s\n", _key.c_str(), ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
571#endif
572
edisonn@google.com571c70b2013-07-10 17:09:50 +0000573 return ret;
574 }
575
edisonn@google.com3aa35552013-08-14 18:26:20 +0000576 const SkPdfNativeObject* get(const SkPdfNativeObject* key) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000577 SkPdfMarkObjectUsed();
578
edisonn@google.com571c70b2013-07-10 17:09:50 +0000579 SkASSERT(fObjectType == kDictionary_PdfObjectType);
580 SkASSERT(key->fObjectType == kName_PdfObjectType);
581
582 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
583 // TODO(edisonn): report err
edisonn@google.com3fc48262013-07-22 15:29:55 +0000584 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000585 }
586
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000587 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
edisonn@google.com571c70b2013-07-10 17:09:50 +0000588
edisonn@google.comd761e322013-07-22 17:29:43 +0000589 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000590 }
591
edisonn@google.com3aa35552013-08-14 18:26:20 +0000592 const SkPdfNativeObject* get(const char* key) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000593 SkPdfMarkObjectUsed();
594
edisonn@google.comd761e322013-07-22 17:29:43 +0000595 return get((const unsigned char*)key, strlen(key));
596 }
597
edisonn@google.com3aa35552013-08-14 18:26:20 +0000598 const SkPdfNativeObject* get(const unsigned char* key, size_t len) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000599 SkPdfMarkObjectUsed();
600
edisonn@google.com571c70b2013-07-10 17:09:50 +0000601 SkASSERT(fObjectType == kDictionary_PdfObjectType);
602 SkASSERT(key);
603 if (fObjectType != kDictionary_PdfObjectType) {
604 // TODO(edisonn): report err
605 return NULL;
606 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000607 SkPdfNativeObject* ret = NULL;
edisonn@google.comd761e322013-07-22 17:29:43 +0000608 fMap->find((const char*)key, len, &ret);
edisonn@google.com9a43c182013-08-01 20:06:42 +0000609
610#ifdef PDF_TRACE
611 SkString _key;
612 _key.append((const char*)key, len);
613 printf("\nget(/%s) = %s\n", _key.c_str(), ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
614#endif
615
edisonn@google.com571c70b2013-07-10 17:09:50 +0000616 return ret;
617 }
618
edisonn@google.com3aa35552013-08-14 18:26:20 +0000619 const SkPdfNativeObject* get(const char* key, const char* abr) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000620 SkPdfMarkObjectUsed();
621
edisonn@google.com3aa35552013-08-14 18:26:20 +0000622 const SkPdfNativeObject* ret = get(key);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000623 // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL
624 // make this distiontion in generator, and remove "" from condition
625 if (ret != NULL || abr == NULL || *abr == '\0') {
626 return ret;
627 }
628 return get(abr);
629 }
630
edisonn@google.com3aa35552013-08-14 18:26:20 +0000631 SkPdfNativeObject* get(const char* key, const char* abr) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000632 SkPdfMarkObjectUsed();
633
edisonn@google.com3aa35552013-08-14 18:26:20 +0000634 SkPdfNativeObject* ret = get(key);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000635 // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL
636 // make this distiontion in generator, and remove "" from condition
637 if (ret != NULL || abr == NULL || *abr == '\0') {
638 return ret;
639 }
640 return get(abr);
641 }
642
643 SkPdfDictionary* asDictionary() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000644 SkPdfMarkObjectUsed();
645
edisonn@google.com571c70b2013-07-10 17:09:50 +0000646 SkASSERT(isDictionary());
647 if (!isDictionary()) {
648 return NULL;
649 }
650 return (SkPdfDictionary*) this;
651 }
652
653 const SkPdfDictionary* asDictionary() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000654 SkPdfMarkObjectUsed();
655
edisonn@google.com571c70b2013-07-10 17:09:50 +0000656 SkASSERT(isDictionary());
657 if (!isDictionary()) {
658 return NULL;
659 }
660 return (SkPdfDictionary*) this;
661 }
662
663
664 bool isReference() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000665 SkPdfMarkObjectUsed();
666
edisonn@google.com571c70b2013-07-10 17:09:50 +0000667 return fObjectType == kReference_PdfObjectType;
668 }
669
670 bool isBoolean() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000671 SkPdfMarkObjectUsed();
672
edisonn@google.com571c70b2013-07-10 17:09:50 +0000673 return fObjectType == kBoolean_PdfObjectType;
674 }
675
676 bool isInteger() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000677 SkPdfMarkObjectUsed();
678
edisonn@google.com571c70b2013-07-10 17:09:50 +0000679 return fObjectType == kInteger_PdfObjectType;
680 }
681private:
682 bool isReal() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000683 SkPdfMarkObjectUsed();
684
edisonn@google.com571c70b2013-07-10 17:09:50 +0000685 return fObjectType == kReal_PdfObjectType;
686 }
687public:
688 bool isNumber() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000689 SkPdfMarkObjectUsed();
690
edisonn@google.com571c70b2013-07-10 17:09:50 +0000691 return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_PdfObjectType;
692 }
693
694 bool isKeywordReference() 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 && fStr.fBytes == 1 && fStr.fBuffer[0] == 'R';
698 }
699
700 bool isKeyword() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000701 SkPdfMarkObjectUsed();
702
edisonn@google.com571c70b2013-07-10 17:09:50 +0000703 return fObjectType == kKeyword_PdfObjectType;
704 }
705
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000706 bool isKeyword(const char* keyword) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000707 SkPdfMarkObjectUsed();
708
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000709 if (!isKeyword()) {
710 return false;
711 }
712
713 if (strlen(keyword) != fStr.fBytes) {
714 return false;
715 }
716
717 if (strncmp(keyword, (const char*)fStr.fBuffer, fStr.fBytes) != 0) {
718 return false;
719 }
720
721 return true;
722 }
723
edisonn@google.com571c70b2013-07-10 17:09:50 +0000724 bool isName() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000725 SkPdfMarkObjectUsed();
726
edisonn@google.com571c70b2013-07-10 17:09:50 +0000727 return fObjectType == kName_PdfObjectType;
728 }
729
edisonn@google.com78b38b12013-07-15 18:20:58 +0000730 bool isName(const char* name) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000731 SkPdfMarkObjectUsed();
732
edisonn@google.com78b38b12013-07-15 18:20:58 +0000733 return fObjectType == kName_PdfObjectType && fStr.fBytes == strlen(name) && strncmp((const char*)fStr.fBuffer, name, fStr.fBytes) == 0;
734 }
735
edisonn@google.com571c70b2013-07-10 17:09:50 +0000736 bool isArray() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000737 SkPdfMarkObjectUsed();
738
edisonn@google.com571c70b2013-07-10 17:09:50 +0000739 return fObjectType == kArray_PdfObjectType;
740 }
741
742 bool isDate() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000743 SkPdfMarkObjectUsed();
744
edisonn@google.com571c70b2013-07-10 17:09:50 +0000745 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
746 }
747
748 bool isDictionary() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000749 SkPdfMarkObjectUsed();
750
edisonn@google.com571c70b2013-07-10 17:09:50 +0000751 return fObjectType == kDictionary_PdfObjectType;
752 }
753
754 bool isFunction() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000755 SkPdfMarkObjectUsed();
756
edisonn@google.com571c70b2013-07-10 17:09:50 +0000757 return false; // NYI
758 }
759
760 bool isRectangle() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000761 SkPdfMarkObjectUsed();
762
edisonn@google.com571c70b2013-07-10 17:09:50 +0000763 return fObjectType == kArray_PdfObjectType && fArray->count() == 4; // NYI + and elems are numbers
764 }
765
766 // TODO(edisonn): has stream .. or is stream ... TBD
767 bool hasStream() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000768 SkPdfMarkObjectUsed();
769
edisonn@google.com571c70b2013-07-10 17:09:50 +0000770 return isDictionary() && fStr.fBuffer != NULL;
771 }
772
773 // TODO(edisonn): has stream .. or is stream ... TBD
774 const SkPdfStream* getStream() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000775 SkPdfMarkObjectUsed();
776
edisonn@google.com571c70b2013-07-10 17:09:50 +0000777 return hasStream() ? (const SkPdfStream*)this : NULL;
778 }
779
780 SkPdfStream* getStream() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000781 SkPdfMarkObjectUsed();
782
edisonn@google.com571c70b2013-07-10 17:09:50 +0000783 return hasStream() ? (SkPdfStream*)this : NULL;
784 }
785
786 bool isAnyString() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000787 SkPdfMarkObjectUsed();
788
edisonn@google.com571c70b2013-07-10 17:09:50 +0000789 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
790 }
791
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000792 bool isHexString() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000793 SkPdfMarkObjectUsed();
794
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000795 return fObjectType == kHexString_PdfObjectType;
796 }
797
edisonn@google.com571c70b2013-07-10 17:09:50 +0000798 bool isMatrix() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000799 SkPdfMarkObjectUsed();
800
edisonn@google.com571c70b2013-07-10 17:09:50 +0000801 return fObjectType == kArray_PdfObjectType && fArray->count() == 6; // NYI + and elems are numbers
802 }
803
804 inline int64_t intValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000805 SkPdfMarkObjectUsed();
806
edisonn@google.com571c70b2013-07-10 17:09:50 +0000807 SkASSERT(fObjectType == kInteger_PdfObjectType);
808
809 if (fObjectType != kInteger_PdfObjectType) {
810 // TODO(edisonn): log err
811 return 0;
812 }
813 return fIntegerValue;
814 }
815private:
816 inline double realValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000817 SkPdfMarkObjectUsed();
818
edisonn@google.com571c70b2013-07-10 17:09:50 +0000819 SkASSERT(fObjectType == kReal_PdfObjectType);
820
821 if (fObjectType != kReal_PdfObjectType) {
822 // TODO(edisonn): log err
823 return 0;
824 }
825 return fRealValue;
826 }
827public:
828 inline double numberValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000829 SkPdfMarkObjectUsed();
830
edisonn@google.com571c70b2013-07-10 17:09:50 +0000831 SkASSERT(isNumber());
832
833 if (!isNumber()) {
834 // TODO(edisonn): log err
835 return 0;
836 }
837 return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue;
838 }
839
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000840 inline SkScalar scalarValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000841 SkPdfMarkObjectUsed();
842
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000843 SkASSERT(isNumber());
844
845 if (!isNumber()) {
846 // TODO(edisonn): log err
847 return SkIntToScalar(0);
848 }
849 return fObjectType == kReal_PdfObjectType ? SkDoubleToScalar(fRealValue) :
850 SkIntToScalar(fIntegerValue);
851 }
852
edisonn@google.com571c70b2013-07-10 17:09:50 +0000853 int referenceId() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000854 SkPdfMarkObjectUsed();
855
edisonn@google.com571c70b2013-07-10 17:09:50 +0000856 SkASSERT(fObjectType == kReference_PdfObjectType);
857 return fRef.fId;
858 }
859
860 int referenceGeneration() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000861 SkPdfMarkObjectUsed();
862
edisonn@google.com571c70b2013-07-10 17:09:50 +0000863 SkASSERT(fObjectType == kReference_PdfObjectType);
864 return fRef.fGen;
865 }
866
867 inline const char* nameValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000868 SkPdfMarkObjectUsed();
869
edisonn@google.com571c70b2013-07-10 17:09:50 +0000870 SkASSERT(fObjectType == kName_PdfObjectType);
871
872 if (fObjectType != kName_PdfObjectType) {
873 // TODO(edisonn): log err
874 return "";
875 }
876 return (const char*)fStr.fBuffer;
877 }
878
879 inline const char* stringValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000880 SkPdfMarkObjectUsed();
881
edisonn@google.com571c70b2013-07-10 17:09:50 +0000882 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
883
884 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
885 // TODO(edisonn): log err
886 return "";
887 }
888 return (const char*)fStr.fBuffer;
889 }
890
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000891 inline NotOwnedString strRef() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000892 SkPdfMarkObjectUsed();
893
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000894 switch (fObjectType) {
895 case kString_PdfObjectType:
896 case kHexString_PdfObjectType:
897 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000898 case kName_PdfObjectType:
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000899 return fStr;
900
901 default:
902 // TODO(edisonn): report/warning
903 return NotOwnedString();
904 }
905 }
906
edisonn@google.com571c70b2013-07-10 17:09:50 +0000907 // TODO(edisonn): nameValue2 and stringValue2 are used to make code generation easy,
908 // but it is not a performat way to do it, since it will create an extra copy
909 // remove these functions and make code generated faster
edisonn@google.com063d7072013-08-16 15:05:08 +0000910 inline SkString nameValue2() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000911 SkPdfMarkObjectUsed();
912
edisonn@google.com571c70b2013-07-10 17:09:50 +0000913 SkASSERT(fObjectType == kName_PdfObjectType);
914
915 if (fObjectType != kName_PdfObjectType) {
916 // TODO(edisonn): log err
edisonn@google.com063d7072013-08-16 15:05:08 +0000917 return SkString();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000918 }
edisonn@google.com063d7072013-08-16 15:05:08 +0000919 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000920 }
921
edisonn@google.com063d7072013-08-16 15:05:08 +0000922 inline SkString stringValue2() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000923 SkPdfMarkObjectUsed();
924
edisonn@google.com571c70b2013-07-10 17:09:50 +0000925 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
926
927 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
928 // TODO(edisonn): log err
edisonn@google.com063d7072013-08-16 15:05:08 +0000929 return SkString();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000930 }
edisonn@google.com063d7072013-08-16 15:05:08 +0000931 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000932 }
933
934 inline bool boolValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000935 SkPdfMarkObjectUsed();
936
edisonn@google.com571c70b2013-07-10 17:09:50 +0000937 SkASSERT(fObjectType == kBoolean_PdfObjectType);
938
edisonn@google.comf111a4b2013-07-31 18:22:36 +0000939 if (fObjectType != kBoolean_PdfObjectType) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000940 // TODO(edisonn): log err
941 return false;
942 }
943 return fBooleanValue;
944 }
945
946 SkRect rectangleValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000947 SkPdfMarkObjectUsed();
948
edisonn@google.com571c70b2013-07-10 17:09:50 +0000949 SkASSERT(isRectangle());
950 if (!isRectangle()) {
951 return SkRect::MakeEmpty();
952 }
953
954 double array[4];
955 for (int i = 0; i < 4; i++) {
956 // TODO(edisonn): version where we could resolve references?
edisonn@google.com3aa35552013-08-14 18:26:20 +0000957 const SkPdfNativeObject* elem = objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000958 if (elem == NULL || !elem->isNumber()) {
959 // TODO(edisonn): report error
960 return SkRect::MakeEmpty();
961 }
962 array[i] = elem->numberValue();
963 }
964
965 return SkRect::MakeLTRB(SkDoubleToScalar(array[0]),
966 SkDoubleToScalar(array[1]),
967 SkDoubleToScalar(array[2]),
968 SkDoubleToScalar(array[3]));
969 }
970
971 SkMatrix matrixValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000972 SkPdfMarkObjectUsed();
973
edisonn@google.com571c70b2013-07-10 17:09:50 +0000974 SkASSERT(isMatrix());
975 if (!isMatrix()) {
976 return SkMatrix::I();
977 }
978
979 double array[6];
980 for (int i = 0; i < 6; i++) {
981 // TODO(edisonn): version where we could resolve references?
edisonn@google.com3aa35552013-08-14 18:26:20 +0000982 const SkPdfNativeObject* elem = objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000983 if (elem == NULL || !elem->isNumber()) {
984 // TODO(edisonn): report error
985 return SkMatrix::I();
986 }
987 array[i] = elem->numberValue();
988 }
989
990 return SkMatrixFromPdfMatrix(array);
991 }
992
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000993 bool filterStream();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000994
995
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000996 bool GetFilteredStreamRef(unsigned char const** buffer, size_t* len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000997 SkPdfMarkObjectUsed();
998
edisonn@google.com571c70b2013-07-10 17:09:50 +0000999 // TODO(edisonn): add params that couls let the last filter in place if it is jpeg or png to fast load images
1000 if (!hasStream()) {
1001 return false;
1002 }
1003
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001004 filterStream();
edisonn@google.com571c70b2013-07-10 17:09:50 +00001005
1006 if (buffer) {
1007 *buffer = fStr.fBuffer;
1008 }
1009
1010 if (len) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001011 *len = fStr.fBytes >> 2; // last 2 bits
edisonn@google.com571c70b2013-07-10 17:09:50 +00001012 }
1013
1014 return true;
1015 }
1016
1017 bool isStreamFiltered() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001018 SkPdfMarkObjectUsed();
1019
edisonn@google.com571c70b2013-07-10 17:09:50 +00001020 return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit);
1021 }
1022
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001023 bool isStreamOwned() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001024 SkPdfMarkObjectUsed();
1025
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001026 return hasStream() && ((fStr.fBytes & 2) == kOwnedStreamBit);
1027 }
1028
1029 bool GetUnfilteredStreamRef(unsigned char const** buffer, size_t* len) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001030 SkPdfMarkObjectUsed();
1031
edisonn@google.com571c70b2013-07-10 17:09:50 +00001032 if (isStreamFiltered()) {
1033 return false;
1034 }
1035
1036 if (!hasStream()) {
1037 return false;
1038 }
1039
1040 if (buffer) {
1041 *buffer = fStr.fBuffer;
1042 }
1043
1044 if (len) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001045 *len = fStr.fBytes >> 2; // remove last 2 bits
edisonn@google.com571c70b2013-07-10 17:09:50 +00001046 }
1047
1048 return true;
1049 }
1050
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001051 bool addStream(const unsigned char* buffer, size_t len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001052 //SkPdfMarkObjectUsed();
1053
edisonn@google.com571c70b2013-07-10 17:09:50 +00001054 SkASSERT(!hasStream());
1055 SkASSERT(isDictionary());
1056
1057 if (!isDictionary() || hasStream()) {
1058 return false;
1059 }
1060
1061 fStr.fBuffer = buffer;
1062 fStr.fBytes = (len << 2) + kUnfilteredStreamBit;
1063
1064 return true;
1065 }
1066
edisonn@google.com276fed92013-08-01 21:20:47 +00001067 static void appendSpaces(SkString* str, int level) {
edisonn@google.com9a43c182013-08-01 20:06:42 +00001068 for (int i = 0 ; i < level; i++) {
1069 str->append(" ");
1070 }
1071 }
1072
edisonn@google.com3aa35552013-08-14 18:26:20 +00001073 static void append(SkString* str, const char* data, size_t len, const char* prefix = "\\x") {
1074 for (unsigned int i = 0 ; i < len; i++) {
1075 if (data[i] == kNUL_PdfWhiteSpace) {
1076 str->append(prefix);
1077 str->append("00");
1078 } else if (data[i] == kHT_PdfWhiteSpace) {
1079 str->append(prefix);
1080 str->append("09");
1081 } else if (data[i] == kLF_PdfWhiteSpace) {
1082 str->append(prefix);
1083 str->append("0A");
1084 } else if (data[i] == kFF_PdfWhiteSpace) {
1085 str->append(prefix);
1086 str->append("0C");
1087 } else if (data[i] == kCR_PdfWhiteSpace) {
1088 str->append(prefix);
1089 str->append("0D");
1090 } else {
1091 str->append(data + i, 1);
1092 }
1093 }
1094 }
1095
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001096 SkString toString(int firstRowLevel = 0, int level = 0) {
edisonn@google.com571c70b2013-07-10 17:09:50 +00001097 SkString str;
edisonn@google.com9a43c182013-08-01 20:06:42 +00001098 appendSpaces(&str, firstRowLevel);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001099 switch (fObjectType) {
1100 case kInvalid_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001101 str.append("__Invalid");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001102 break;
1103
1104 case kBoolean_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001105 str.appendf("%s", fBooleanValue ? "true" : "false");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001106 break;
1107
1108 case kInteger_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001109 str.appendf("%i", (int)fIntegerValue);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001110 break;
1111
1112 case kReal_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001113 str.appendf("%f", fRealValue);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001114 break;
1115
1116 case kString_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001117 str.append("\"");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001118 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com9a43c182013-08-01 20:06:42 +00001119 str.append("\"");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001120 break;
1121
1122 case kHexString_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001123 str.append("<");
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001124 for (unsigned int i = 0 ; i < fStr.fBytes; i++) {
1125 str.appendf("%02x", (unsigned int)fStr.fBuffer[i]);
1126 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001127 str.append(">");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001128 break;
1129
1130 case kName_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001131 str.append("/");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001132 append(&str, (const char*)fStr.fBuffer, fStr.fBytes, "#");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001133 break;
1134
1135 case kKeyword_PdfObjectType:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001136 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001137 break;
1138
1139 case kArray_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001140 str.append("[\n");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001141 for (unsigned int i = 0; i < size(); i++) {
edisonn@google.com9a43c182013-08-01 20:06:42 +00001142 str.append(objAtAIndex(i)->toString(level + 1, level + 1));
1143 if (i < size() - 1) {
1144 str.append(",");
1145 }
1146 str.append("\n");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001147 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001148 appendSpaces(&str, level);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001149 str.append("]");
1150 break;
1151
edisonn@google.com9a43c182013-08-01 20:06:42 +00001152 case kDictionary_PdfObjectType: {
edisonn@google.com3aa35552013-08-14 18:26:20 +00001153 SkTDict<SkPdfNativeObject*>::Iter iter(*fMap);
1154 SkPdfNativeObject* obj = NULL;
edisonn@google.com9a43c182013-08-01 20:06:42 +00001155 const char* key = NULL;
1156 str.append("<<\n");
1157 while ((key = iter.next(&obj)) != NULL) {
1158 appendSpaces(&str, level + 2);
1159 str.appendf("/%s %s\n", key, obj->toString(0, level + strlen(key) + 4).c_str());
1160 }
1161 appendSpaces(&str, level);
1162 str.append(">>");
1163 if (hasStream()) {
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001164 const unsigned char* stream = NULL;
1165 size_t length = 0;
1166 if (GetFilteredStreamRef(&stream, &length)) {
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001167 str.append("stream\n");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001168 append(&str, (const char*)stream, length > 256 ? 256 : length);
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001169 str.append("\nendstream");
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001170 } else {
1171 str.append("stream STREAM_ERROR endstream");
1172 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001173 }
edisonn@google.com571c70b2013-07-10 17:09:50 +00001174 }
1175 break;
1176
1177 case kNull_PdfObjectType:
1178 str = "NULL";
1179 break;
1180
1181 case kReference_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001182 str.appendf("%i %i R", fRef.fId, fRef.fGen);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001183 break;
1184
1185 case kUndefined_PdfObjectType:
1186 str = "Undefined";
1187 break;
1188
1189 default:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001190 str = "Error";
edisonn@google.com571c70b2013-07-10 17:09:50 +00001191 break;
1192 }
1193
1194 return str;
1195 }
1196
1197private:
edisonn@google.combca421b2013-09-05 20:00:21 +00001198 static void makeStringCore(const unsigned char* start, SkPdfNativeObject* obj, ObjectType type GET_TRACK_PARAMETERS) {
1199 makeStringCore(start, strlen((const char*)start), obj, type PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001200 }
1201
edisonn@google.combca421b2013-09-05 20:00:21 +00001202 static void makeStringCore(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj, ObjectType type GET_TRACK_PARAMETERS) {
1203 makeStringCore(start, end - start, obj, type PUT_TRACK_PARAMETERS);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001204 }
1205
edisonn@google.combca421b2013-09-05 20:00:21 +00001206 static void makeStringCore(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj, ObjectType type GET_TRACK_PARAMETERS) {
1207 STORE_TRACK_PARAMETERS(obj);
1208
edisonn@google.com571c70b2013-07-10 17:09:50 +00001209 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
1210
1211 obj->fObjectType = type;
1212 obj->fStr.fBuffer = start;
1213 obj->fStr.fBytes = bytes;
1214 }
1215
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001216 bool applyFilter(const char* name);
1217 bool applyFlateDecodeFilter();
1218 bool applyDCTDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +00001219};
1220
edisonn@google.com3aa35552013-08-14 18:26:20 +00001221class SkPdfStream : public SkPdfNativeObject {};
1222class SkPdfArray : public SkPdfNativeObject {};
1223class SkPdfString : public SkPdfNativeObject {};
1224class SkPdfHexString : public SkPdfNativeObject {};
1225class SkPdfInteger : public SkPdfNativeObject {};
1226class SkPdfReal : public SkPdfNativeObject {};
1227class SkPdfNumber : public SkPdfNativeObject {};
edisonn@google.com571c70b2013-07-10 17:09:50 +00001228
edisonn@google.com3aa35552013-08-14 18:26:20 +00001229class SkPdfName : public SkPdfNativeObject {
1230 SkPdfName() : SkPdfNativeObject() {
edisonn@google.combca421b2013-09-05 20:00:21 +00001231 SkPdfNativeObject::makeName((const unsigned char*)"", this PUT_TRACK_PARAMETERS_SRC);
edisonn@google.com78b38b12013-07-15 18:20:58 +00001232 }
1233public:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001234 SkPdfName(char* name) : SkPdfNativeObject() {
edisonn@google.combca421b2013-09-05 20:00:21 +00001235 this->makeName((const unsigned char*)name, this PUT_TRACK_PARAMETERS_SRC);
edisonn@google.com78b38b12013-07-15 18:20:58 +00001236 }
1237};
1238
edisonn@google.comcf2cfa12013-08-21 16:31:37 +00001239#endif // SkPdfNativeObject