blob: b9d5d03bed8afba768fd94fe338cbe1f60a1c21a [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.comc8fda9d2013-10-09 20:23:12 +000013
14#include "SkMatrix.h"
15#include "SkPdfConfig.h"
16#include "SkPdfNativeTokenizer.h"
17#include "SkPdfNYI.h"
18#include "SkPdfUtils.h"
19#include "SkRect.h"
edisonn@google.com063d7072013-08-16 15:05:08 +000020#include "SkString.h"
edisonn@google.com571c70b2013-07-10 17:09:50 +000021#include "SkTDArray.h"
22#include "SkTDict.h"
edisonn@google.com571c70b2013-07-10 17:09:50 +000023
24class SkPdfDictionary;
25class SkPdfStream;
26class SkPdfAllocator;
27
edisonn@google.comc8fda9d2013-10-09 20:23:12 +000028// TODO(edisonn): remove these constants and clean up the code.
edisonn@google.com571c70b2013-07-10 17:09:50 +000029#define kFilteredStreamBit 0
30#define kUnfilteredStreamBit 1
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000031#define kOwnedStreamBit 2
edisonn@google.com571c70b2013-07-10 17:09:50 +000032
edisonn@google.com3aa35552013-08-14 18:26:20 +000033class SkPdfNativeObject {
edisonn@google.com571c70b2013-07-10 17:09:50 +000034 public:
35 enum ObjectType {
edisonn@google.comaf54a512013-09-13 19:33:42 +000036 // The type will have only one of these values, but for error reporting, we make it an enum
37 // so it can easily report that something was expected to be one of a few types
38 kInvalid_PdfObjectType = 1 << 1,
edisonn@google.com571c70b2013-07-10 17:09:50 +000039
edisonn@google.comaf54a512013-09-13 19:33:42 +000040 kBoolean_PdfObjectType = 1 << 2,
41 kInteger_PdfObjectType = 1 << 3,
42 kReal_PdfObjectType = 1 << 4,
43 _kNumber_PdfObjectType = kInteger_PdfObjectType | kReal_PdfObjectType,
44 kString_PdfObjectType = 1 << 5,
45 kHexString_PdfObjectType = 1 << 6,
46 _kAnyString_PdfObjectType = kString_PdfObjectType | kHexString_PdfObjectType,
47 kName_PdfObjectType = 1 << 7,
48 kKeyword_PdfObjectType = 1 << 8,
49 _kStream_PdfObjectType = 1 << 9, // attached to a Dictionary, do not use
50 kArray_PdfObjectType = 1 << 10,
51 kDictionary_PdfObjectType = 1 << 11,
52 kNull_PdfObjectType = 1 << 12,
edisonn@google.com571c70b2013-07-10 17:09:50 +000053
edisonn@google.comaf54a512013-09-13 19:33:42 +000054 kReference_PdfObjectType = 1 << 13,
edisonn@google.com571c70b2013-07-10 17:09:50 +000055
edisonn@google.comc8fda9d2013-10-09 20:23:12 +000056 kUndefined_PdfObjectType = 1 << 14, // per 1.4 spec, if the same key appear twice in the
57 // dictionary, the value is undefined.
edisonn@google.comaf54a512013-09-13 19:33:42 +000058
59 _kObject_PdfObjectType = -1,
edisonn@google.com571c70b2013-07-10 17:09:50 +000060 };
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.comc8fda9d2013-10-09 20:23:12 +000069 // TODO(edisonn): assert reset operations while in rendering! The objects should be reset
70 // only when rendering is completed.
edisonn@google.com063d7072013-08-16 15:05:08 +000071 uint32_t fInRendering : 1;
72 uint32_t fUnused : 31;
73
edisonn@google.com571c70b2013-07-10 17:09:50 +000074 struct Reference {
75 unsigned int fId;
76 unsigned int fGen;
77 };
78
edisonn@google.com571c70b2013-07-10 17:09:50 +000079 ObjectType fObjectType;
80
81 union {
82 bool fBooleanValue;
83 int64_t fIntegerValue;
edisonn@google.comc8fda9d2013-10-09 20:23:12 +000084 // TODO(edisonn): double, float, SkScalar?
edisonn@google.com571c70b2013-07-10 17:09:50 +000085 double fRealValue;
86 NotOwnedString fStr;
87
edisonn@google.com3aa35552013-08-14 18:26:20 +000088 SkTDArray<SkPdfNativeObject*>* fArray;
edisonn@google.com571c70b2013-07-10 17:09:50 +000089 Reference fRef;
90 };
edisonn@google.com3aa35552013-08-14 18:26:20 +000091 SkTDict<SkPdfNativeObject*>* fMap;
edisonn@google.comb0145ce2013-08-05 16:23:23 +000092
93 // TODO(edisonn): rename data with cache
edisonn@google.com571c70b2013-07-10 17:09:50 +000094 void* fData;
edisonn@google.comb0145ce2013-08-05 16:23:23 +000095 DataType fDataType;
edisonn@google.com571c70b2013-07-10 17:09:50 +000096
edisonn@google.combca421b2013-09-05 20:00:21 +000097 // Keep this the last entries
edisonn@google.com0fd25d82013-09-05 16:40:34 +000098#ifdef PDF_TRACK_OBJECT_USAGE
99 mutable bool fUsed;
100#endif // PDF_TRACK_OBJECT_USAGE
101
edisonn@google.combca421b2013-09-05 20:00:21 +0000102#ifdef PDF_TRACK_STREAM_OFFSETS
edisonn@google.com571c70b2013-07-10 17:09:50 +0000103public:
edisonn@google.combca421b2013-09-05 20:00:21 +0000104 int fStreamId;
105 int fOffsetStart;
106 int fOffsetEnd;
107#endif // PDF_TRACK_STREAM_OFFSETS
108
109public:
110
111#ifdef PDF_TRACK_STREAM_OFFSETS
112 int streamId() const { return fStreamId; }
113 int offsetStart() const { return fOffsetStart; }
114 int offsetEnd() const { return fOffsetEnd; }
115#endif // PDF_TRACK_STREAM_OFFSETS
116
edisonn@google.com571c70b2013-07-10 17:09:50 +0000117
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000118 SkPdfNativeObject() : fInRendering(0)
119 , fObjectType(kInvalid_PdfObjectType)
120 , fMap(NULL)
121 , fData(NULL)
122 , fDataType(kEmpty_Data)
123#ifdef PDF_TRACK_OBJECT_USAGE
124 , fUsed(false)
125#endif // PDF_TRACK_OBJECT_USAGE
edisonn@google.combca421b2013-09-05 20:00:21 +0000126
127#ifdef PDF_TRACK_STREAM_OFFSETS
128 , fStreamId(-1)
129 , fOffsetStart(-1)
130 , fOffsetEnd(-1)
131#endif // PDF_TRACK_STREAM_OFFSETS
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000132 {}
edisonn@google.com571c70b2013-07-10 17:09:50 +0000133
edisonn@google.com063d7072013-08-16 15:05:08 +0000134 bool inRendering() const { return fInRendering != 0; }
135 void startRendering() {fInRendering = 1;}
136 void doneRendering() {fInRendering = 0;}
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000137
138 inline bool hasData(DataType type) {
139 return type == fDataType;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000140 }
141
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000142 inline void* data(DataType type) {
143 return type == fDataType ? fData : NULL;
144 }
145
146 inline void setData(void* data, DataType type) {
147 releaseData();
148 fDataType = type;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000149 fData = data;
150 }
151
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000152 void releaseData();
153
edisonn@google.com3aa35552013-08-14 18:26:20 +0000154// ~SkPdfNativeObject() {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000155// //reset(); must be called manually! Normally, will be called by allocator destructor.
edisonn@google.com222382b2013-07-10 22:33:10 +0000156// }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000157
158 void reset() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000159 SkPdfMarkObjectUnused();
160
edisonn@google.com571c70b2013-07-10 17:09:50 +0000161 switch (fObjectType) {
162 case kArray_PdfObjectType:
163 delete fArray;
164 break;
165
166 case kDictionary_PdfObjectType:
167 delete fMap;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000168 if (isStreamOwned()) {
169 delete[] fStr.fBuffer;
170 fStr.fBuffer = NULL;
171 fStr.fBytes = 0;
172 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000173 break;
174
175 default:
176 break;
177 }
178 fObjectType = kInvalid_PdfObjectType;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000179 releaseData();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000180 }
181
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000182 ObjectType type() {
183 SkPdfMarkObjectUsed();
184
185 return fObjectType;
186 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000187
188 const char* c_str() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000189 SkPdfMarkObjectUsed();
190
edisonn@google.com571c70b2013-07-10 17:09:50 +0000191 switch (fObjectType) {
192 case kString_PdfObjectType:
193 case kHexString_PdfObjectType:
194 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000195 case kName_PdfObjectType:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000196 return (const char*)fStr.fBuffer;
197
198 default:
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000199 // TODO(edisonn): report/warning/assert?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000200 return NULL;
201 }
202 }
203
edisonn@google.come878e722013-07-29 19:10:58 +0000204 size_t lenstr() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000205 SkPdfMarkObjectUsed();
206
edisonn@google.com571c70b2013-07-10 17:09:50 +0000207 switch (fObjectType) {
208 case kString_PdfObjectType:
209 case kHexString_PdfObjectType:
210 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000211 case kName_PdfObjectType:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000212 return fStr.fBytes;
213
214 default:
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000215 // TODO(edisonn): report/warning/assert?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000216 return 0;
217 }
218 }
219
220
221 // TODO(edisonn): NYI
222 SkPdfDate& dateValue() const {
223 static SkPdfDate nyi;
224 return nyi;
225 }
226
227 // TODO(edisonn): NYI
228 SkPdfFunction& functionValue() const {
229 static SkPdfFunction nyi;
230 return nyi;
231 }
232
233 // TODO(edisonn): NYI
234 SkPdfFileSpec& fileSpecValue() const {
235 static SkPdfFileSpec nyi;
236 return nyi;
237 }
238
239 // TODO(edisonn): NYI
240 SkPdfTree& treeValue() const {
241 static SkPdfTree nyi;
242 return nyi;
243 }
244
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000245 static void makeBoolean(bool value, SkPdfNativeObject* obj) {
edisonn@google.combca421b2013-09-05 20:00:21 +0000246
edisonn@google.com571c70b2013-07-10 17:09:50 +0000247 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
248
249 obj->fObjectType = kBoolean_PdfObjectType;
250 obj->fBooleanValue = value;
251 }
252
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000253 static SkPdfNativeObject makeBoolean(bool value) {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000254 SkPdfNativeObject obj;
edisonn@google.combca421b2013-09-05 20:00:21 +0000255
edisonn@google.com571c70b2013-07-10 17:09:50 +0000256 obj.fObjectType = kBoolean_PdfObjectType;
257 obj.fBooleanValue = value;
258 return obj;
259 }
260
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000261 static void makeInteger(int64_t value, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000262 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
263
264 obj->fObjectType = kInteger_PdfObjectType;
265 obj->fIntegerValue = value;
266 }
267
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000268 static void makeReal(double value, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000269 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
270
271 obj->fObjectType = kReal_PdfObjectType;
272 obj->fRealValue = value;
273 }
274
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000275 static void makeNull(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000276 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
277
278 obj->fObjectType = kNull_PdfObjectType;
279 }
280
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000281 static SkPdfNativeObject makeNull() {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000282 SkPdfNativeObject obj;
edisonn@google.combca421b2013-09-05 20:00:21 +0000283
edisonn@google.com571c70b2013-07-10 17:09:50 +0000284 obj.fObjectType = kNull_PdfObjectType;
285 return obj;
286 }
287
edisonn@google.com3aa35552013-08-14 18:26:20 +0000288 static SkPdfNativeObject kNull;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000289
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000290 static void makeNumeric(const unsigned char* start, const unsigned char* end,
291 SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000292 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
293
294 // TODO(edisonn): NYI properly
295 // if has dot (impl), or exceeds max int, is real, otherwise is int
296 bool isInt = true;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000297 for (const unsigned char* current = start; current < end; current++) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000298 if (*current == '.') {
299 isInt = false;
300 break;
301 }
302 // TODO(edisonn): report parse issue with numbers like "24asdasd123"
303 }
304 if (isInt) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000305 makeInteger(atol((const char*)start), obj);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000306 } else {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000307 makeReal(atof((const char*)start), obj);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000308 }
309 }
310
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000311 static void makeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000312 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
313
314 obj->fObjectType = kReference_PdfObjectType;
315 obj->fRef.fId = id;
316 obj->fRef.fGen = gen;
317 }
318
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000319 static void resetAndMakeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj) {
edisonn@google.combca421b2013-09-05 20:00:21 +0000320 obj->reset();
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000321 makeReference(id, gen, obj);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000322 }
323
324
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000325 static void makeString(const unsigned char* start, SkPdfNativeObject* obj) {
326 makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000327 }
328
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000329 static void makeString(const unsigned char* start, const unsigned char* end,
330 SkPdfNativeObject* obj) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000331 makeStringCore(start, end - start, obj, kString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000332 }
333
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000334 static void makeString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
335 makeStringCore(start, bytes, obj, kString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000336 }
337
338
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000339 static void makeHexString(const unsigned char* start, SkPdfNativeObject* obj) {
340 makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000341 }
342
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000343 static void makeHexString(const unsigned char* start, const unsigned char* end,
344 SkPdfNativeObject* obj) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000345 makeStringCore(start, end - start, obj, kHexString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000346 }
347
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000348 static void makeHexString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
349 makeStringCore(start, bytes, obj, kHexString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000350 }
351
352
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000353 static void makeName(const unsigned char* start, SkPdfNativeObject* obj) {
354 makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000355 }
356
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000357 static void makeName(const unsigned char* start, const unsigned char* end,
358 SkPdfNativeObject* obj) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000359 makeStringCore(start, end - start, obj, kName_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000360 }
361
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000362 static void makeName(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
363 makeStringCore(start, bytes, obj, kName_PdfObjectType);
edisonn@google.combca421b2013-09-05 20:00:21 +0000364 }
365
366
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000367 static void makeKeyword(const unsigned char* start, SkPdfNativeObject* obj) {
368 makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType);
edisonn@google.combca421b2013-09-05 20:00:21 +0000369 }
370
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000371 static void makeKeyword(const unsigned char* start, const unsigned char* end,
372 SkPdfNativeObject* obj) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000373 makeStringCore(start, end - start, obj, kKeyword_PdfObjectType);
edisonn@google.combca421b2013-09-05 20:00:21 +0000374 }
375
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000376 static void makeKeyword(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
377 makeStringCore(start, bytes, obj, kKeyword_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000378 }
379
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000380 static void makeEmptyArray(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000381 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
382
383 obj->fObjectType = kArray_PdfObjectType;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000384 obj->fArray = new SkTDArray<SkPdfNativeObject*>();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000385 }
386
edisonn@google.com3aa35552013-08-14 18:26:20 +0000387 bool appendInArray(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000388 SkASSERT(fObjectType == kArray_PdfObjectType);
389 if (fObjectType != kArray_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000390 // TODO(edisonn): report/warning/assert?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000391 return false;
392 }
393
394 fArray->push(obj);
395 return true;
396 }
397
398 size_t size() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000399 SkPdfMarkObjectUsed();
400
edisonn@google.com571c70b2013-07-10 17:09:50 +0000401 SkASSERT(fObjectType == kArray_PdfObjectType);
402
403 return fArray->count();
404 }
405
edisonn@google.com3aa35552013-08-14 18:26:20 +0000406 SkPdfNativeObject* objAtAIndex(int i) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000407 SkPdfMarkObjectUsed();
408
edisonn@google.com571c70b2013-07-10 17:09:50 +0000409 SkASSERT(fObjectType == kArray_PdfObjectType);
410
411 return (*fArray)[i];
412 }
413
edisonn@google.com3aa35552013-08-14 18:26:20 +0000414 SkPdfNativeObject* removeLastInArray() {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000415 SkPdfMarkObjectUsed();
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000416
edisonn@google.com571c70b2013-07-10 17:09:50 +0000417 SkASSERT(fObjectType == kArray_PdfObjectType);
418
edisonn@google.com3aa35552013-08-14 18:26:20 +0000419 SkPdfNativeObject* ret = NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000420 fArray->pop(&ret);
421
422 return ret;
423 }
424
edisonn@google.com3aa35552013-08-14 18:26:20 +0000425 const SkPdfNativeObject* objAtAIndex(int i) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000426 SkPdfMarkObjectUsed();
427
edisonn@google.com571c70b2013-07-10 17:09:50 +0000428 SkASSERT(fObjectType == kArray_PdfObjectType);
429
430 return (*fArray)[i];
431 }
432
edisonn@google.com3aa35552013-08-14 18:26:20 +0000433 SkPdfNativeObject* operator[](int i) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000434 SkPdfMarkObjectUsed();
435
edisonn@google.com571c70b2013-07-10 17:09:50 +0000436 SkASSERT(fObjectType == kArray_PdfObjectType);
437
438 return (*fArray)[i];
439 }
440
edisonn@google.com3aa35552013-08-14 18:26:20 +0000441 const SkPdfNativeObject* operator[](int i) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000442 SkPdfMarkObjectUsed();
443
edisonn@google.com571c70b2013-07-10 17:09:50 +0000444 SkASSERT(fObjectType == kArray_PdfObjectType);
445
446 return (*fArray)[i];
447 }
448
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000449 static void makeEmptyDictionary(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000450 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
451
452 obj->fObjectType = kDictionary_PdfObjectType;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000453 obj->fMap = new SkTDict<SkPdfNativeObject*>(1);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000454 obj->fStr.fBuffer = NULL;
455 obj->fStr.fBytes = 0;
456 }
457
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000458 // TODO(edisonn): perf: get all the possible names from spec, and compute a hash function
edisonn@google.com571c70b2013-07-10 17:09:50 +0000459 // that would create no overlaps in the same dictionary
460 // or build a tree of chars that when followed goes to a unique id/index/hash
461 // TODO(edisonn): generate constants like kDictFoo, kNameDict_name
462 // which will be used in code
463 // add function SkPdfFastNameKey key(const char* key);
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000464 // TODO(edisonn): setting the same key twice, will make the value undefined!
edisonn@google.com3aa35552013-08-14 18:26:20 +0000465 bool set(const SkPdfNativeObject* key, SkPdfNativeObject* value) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000466 SkPdfMarkObjectUsed();
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000467
edisonn@google.com571c70b2013-07-10 17:09:50 +0000468 SkASSERT(fObjectType == kDictionary_PdfObjectType);
469 SkASSERT(key->fObjectType == kName_PdfObjectType);
470
471 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000472 // TODO(edisonn): report/warn/assert?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000473 return false;
474 }
475
edisonn@google.comd761e322013-07-22 17:29:43 +0000476 return set(key->fStr.fBuffer, key->fStr.fBytes, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000477 }
478
edisonn@google.com3aa35552013-08-14 18:26:20 +0000479 bool set(const char* key, SkPdfNativeObject* value) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000480 SkPdfMarkObjectUsed();
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000481
edisonn@google.comd761e322013-07-22 17:29:43 +0000482 return set((const unsigned char*)key, strlen(key), value);
483 }
484
edisonn@google.com3aa35552013-08-14 18:26:20 +0000485 bool set(const unsigned char* key, size_t len, SkPdfNativeObject* value) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000486 SkPdfMarkObjectUsed();
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000487
edisonn@google.com571c70b2013-07-10 17:09:50 +0000488 SkASSERT(fObjectType == kDictionary_PdfObjectType);
489
490 if (fObjectType != kDictionary_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000491 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000492 return false;
493 }
494
edisonn@google.comd761e322013-07-22 17:29:43 +0000495 return fMap->set((const char*)key, len, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000496 }
497
edisonn@google.com3aa35552013-08-14 18:26:20 +0000498 SkPdfNativeObject* get(const SkPdfNativeObject* key) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000499 SkPdfMarkObjectUsed();
500
edisonn@google.com571c70b2013-07-10 17:09:50 +0000501 SkASSERT(fObjectType == kDictionary_PdfObjectType);
502 SkASSERT(key->fObjectType == kName_PdfObjectType);
503
504 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000505 // TODO(edisonn): report/warn/assert.
edisonn@google.com3fc48262013-07-22 15:29:55 +0000506 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000507 }
508
edisonn@google.comd761e322013-07-22 17:29:43 +0000509 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000510 }
511
edisonn@google.com3aa35552013-08-14 18:26:20 +0000512 SkPdfNativeObject* get(const char* key) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000513 SkPdfMarkObjectUsed();
514
edisonn@google.comd761e322013-07-22 17:29:43 +0000515 return get((const unsigned char*)key, strlen(key));
516 }
517
edisonn@google.com3aa35552013-08-14 18:26:20 +0000518 SkPdfNativeObject* get(const unsigned char* key, size_t len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000519 SkPdfMarkObjectUsed();
520
edisonn@google.com571c70b2013-07-10 17:09:50 +0000521 SkASSERT(fObjectType == kDictionary_PdfObjectType);
522 SkASSERT(key);
523 if (fObjectType != kDictionary_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000524 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000525 return NULL;
526 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000527 SkPdfNativeObject* ret = NULL;
edisonn@google.comd761e322013-07-22 17:29:43 +0000528 fMap->find((const char*)key, len, &ret);
edisonn@google.com9a43c182013-08-01 20:06:42 +0000529
530#ifdef PDF_TRACE
531 SkString _key;
532 _key.append((const char*)key, len);
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000533 printf("\nget(/%s) = %s\n", _key.c_str(),
534 ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
edisonn@google.com9a43c182013-08-01 20:06:42 +0000535#endif
536
edisonn@google.com571c70b2013-07-10 17:09:50 +0000537 return ret;
538 }
539
edisonn@google.com3aa35552013-08-14 18:26:20 +0000540 const SkPdfNativeObject* get(const SkPdfNativeObject* key) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000541 SkPdfMarkObjectUsed();
542
edisonn@google.com571c70b2013-07-10 17:09:50 +0000543 SkASSERT(fObjectType == kDictionary_PdfObjectType);
544 SkASSERT(key->fObjectType == kName_PdfObjectType);
545
546 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000547 // TODO(edisonn): report/warn/assert.
edisonn@google.com3fc48262013-07-22 15:29:55 +0000548 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000549 }
550
edisonn@google.comd761e322013-07-22 17:29:43 +0000551 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000552 }
553
edisonn@google.com3aa35552013-08-14 18:26:20 +0000554 const SkPdfNativeObject* get(const char* key) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000555 SkPdfMarkObjectUsed();
556
edisonn@google.comd761e322013-07-22 17:29:43 +0000557 return get((const unsigned char*)key, strlen(key));
558 }
559
edisonn@google.com3aa35552013-08-14 18:26:20 +0000560 const SkPdfNativeObject* get(const unsigned char* key, size_t len) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000561 SkPdfMarkObjectUsed();
562
edisonn@google.com571c70b2013-07-10 17:09:50 +0000563 SkASSERT(fObjectType == kDictionary_PdfObjectType);
564 SkASSERT(key);
565 if (fObjectType != kDictionary_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000566 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000567 return NULL;
568 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000569 SkPdfNativeObject* ret = NULL;
edisonn@google.comd761e322013-07-22 17:29:43 +0000570 fMap->find((const char*)key, len, &ret);
edisonn@google.com9a43c182013-08-01 20:06:42 +0000571
572#ifdef PDF_TRACE
573 SkString _key;
574 _key.append((const char*)key, len);
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000575 printf("\nget(/%s) = %s\n", _key.c_str(),
576 ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
edisonn@google.com9a43c182013-08-01 20:06:42 +0000577#endif
578
edisonn@google.com571c70b2013-07-10 17:09:50 +0000579 return ret;
580 }
581
edisonn@google.com3aa35552013-08-14 18:26:20 +0000582 const SkPdfNativeObject* get(const char* key, const char* abr) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000583 SkPdfMarkObjectUsed();
584
edisonn@google.com3aa35552013-08-14 18:26:20 +0000585 const SkPdfNativeObject* ret = get(key);
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000586 // TODO(edisonn): remove || *abr == '\0' and pass NULL in the _autogen files instead.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000587 if (ret != NULL || abr == NULL || *abr == '\0') {
588 return ret;
589 }
590 return get(abr);
591 }
592
edisonn@google.com3aa35552013-08-14 18:26:20 +0000593 SkPdfNativeObject* get(const char* key, const char* abr) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000594 SkPdfMarkObjectUsed();
595
edisonn@google.com3aa35552013-08-14 18:26:20 +0000596 SkPdfNativeObject* ret = get(key);
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000597 // TODO(edisonn): remove || *abr == '\0' and pass NULL in the _autogen files instead.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000598 if (ret != NULL || abr == NULL || *abr == '\0') {
599 return ret;
600 }
601 return get(abr);
602 }
603
604 SkPdfDictionary* asDictionary() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000605 SkPdfMarkObjectUsed();
606
edisonn@google.com571c70b2013-07-10 17:09:50 +0000607 SkASSERT(isDictionary());
608 if (!isDictionary()) {
609 return NULL;
610 }
611 return (SkPdfDictionary*) this;
612 }
613
614 const SkPdfDictionary* asDictionary() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000615 SkPdfMarkObjectUsed();
616
edisonn@google.com571c70b2013-07-10 17:09:50 +0000617 SkASSERT(isDictionary());
618 if (!isDictionary()) {
619 return NULL;
620 }
621 return (SkPdfDictionary*) this;
622 }
623
624
625 bool isReference() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000626 SkPdfMarkObjectUsed();
627
edisonn@google.com571c70b2013-07-10 17:09:50 +0000628 return fObjectType == kReference_PdfObjectType;
629 }
630
631 bool isBoolean() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000632 SkPdfMarkObjectUsed();
633
edisonn@google.com571c70b2013-07-10 17:09:50 +0000634 return fObjectType == kBoolean_PdfObjectType;
635 }
636
637 bool isInteger() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000638 SkPdfMarkObjectUsed();
639
edisonn@google.com571c70b2013-07-10 17:09:50 +0000640 return fObjectType == kInteger_PdfObjectType;
641 }
642private:
643 bool isReal() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000644 SkPdfMarkObjectUsed();
645
edisonn@google.com571c70b2013-07-10 17:09:50 +0000646 return fObjectType == kReal_PdfObjectType;
647 }
648public:
649 bool isNumber() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000650 SkPdfMarkObjectUsed();
651
edisonn@google.com571c70b2013-07-10 17:09:50 +0000652 return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_PdfObjectType;
653 }
654
655 bool isKeywordReference() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000656 SkPdfMarkObjectUsed();
657
edisonn@google.com571c70b2013-07-10 17:09:50 +0000658 return fObjectType == kKeyword_PdfObjectType && fStr.fBytes == 1 && fStr.fBuffer[0] == 'R';
659 }
660
661 bool isKeyword() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000662 SkPdfMarkObjectUsed();
663
edisonn@google.com571c70b2013-07-10 17:09:50 +0000664 return fObjectType == kKeyword_PdfObjectType;
665 }
666
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000667 bool isKeyword(const char* keyword) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000668 SkPdfMarkObjectUsed();
669
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000670 if (!isKeyword()) {
671 return false;
672 }
673
674 if (strlen(keyword) != fStr.fBytes) {
675 return false;
676 }
677
678 if (strncmp(keyword, (const char*)fStr.fBuffer, fStr.fBytes) != 0) {
679 return false;
680 }
681
682 return true;
683 }
684
edisonn@google.com571c70b2013-07-10 17:09:50 +0000685 bool isName() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000686 SkPdfMarkObjectUsed();
687
edisonn@google.com571c70b2013-07-10 17:09:50 +0000688 return fObjectType == kName_PdfObjectType;
689 }
690
edisonn@google.com78b38b12013-07-15 18:20:58 +0000691 bool isName(const char* name) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000692 SkPdfMarkObjectUsed();
693
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000694 return fObjectType == kName_PdfObjectType &&
695 fStr.fBytes == strlen(name) &&
696 strncmp((const char*)fStr.fBuffer, name, fStr.fBytes) == 0;
edisonn@google.com78b38b12013-07-15 18:20:58 +0000697 }
698
edisonn@google.com571c70b2013-07-10 17:09:50 +0000699 bool isArray() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000700 SkPdfMarkObjectUsed();
701
edisonn@google.com571c70b2013-07-10 17:09:50 +0000702 return fObjectType == kArray_PdfObjectType;
703 }
704
705 bool isDate() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000706 SkPdfMarkObjectUsed();
707
edisonn@google.com571c70b2013-07-10 17:09:50 +0000708 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
709 }
710
711 bool isDictionary() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000712 SkPdfMarkObjectUsed();
713
edisonn@google.com571c70b2013-07-10 17:09:50 +0000714 return fObjectType == kDictionary_PdfObjectType;
715 }
716
717 bool isFunction() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000718 SkPdfMarkObjectUsed();
719
edisonn@google.com571c70b2013-07-10 17:09:50 +0000720 return false; // NYI
721 }
722
723 bool isRectangle() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000724 SkPdfMarkObjectUsed();
725
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000726 // TODO(edisonn): add also that each of these 4 objects are numbers.
727 return fObjectType == kArray_PdfObjectType && fArray->count() == 4;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000728 }
729
730 // TODO(edisonn): has stream .. or is stream ... TBD
731 bool hasStream() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000732 SkPdfMarkObjectUsed();
733
edisonn@google.com571c70b2013-07-10 17:09:50 +0000734 return isDictionary() && fStr.fBuffer != NULL;
735 }
736
737 // TODO(edisonn): has stream .. or is stream ... TBD
738 const SkPdfStream* getStream() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000739 SkPdfMarkObjectUsed();
740
edisonn@google.com571c70b2013-07-10 17:09:50 +0000741 return hasStream() ? (const SkPdfStream*)this : NULL;
742 }
743
744 SkPdfStream* getStream() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000745 SkPdfMarkObjectUsed();
746
edisonn@google.com571c70b2013-07-10 17:09:50 +0000747 return hasStream() ? (SkPdfStream*)this : NULL;
748 }
749
750 bool isAnyString() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000751 SkPdfMarkObjectUsed();
752
edisonn@google.com571c70b2013-07-10 17:09:50 +0000753 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
754 }
755
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000756 bool isHexString() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000757 SkPdfMarkObjectUsed();
758
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000759 return fObjectType == kHexString_PdfObjectType;
760 }
761
edisonn@google.com571c70b2013-07-10 17:09:50 +0000762 bool isMatrix() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000763 SkPdfMarkObjectUsed();
764
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000765 // TODO(edisonn): add also that each of these 6 objects are numbers.
766 return fObjectType == kArray_PdfObjectType && fArray->count() == 6;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000767 }
768
769 inline int64_t intValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000770 SkPdfMarkObjectUsed();
771
edisonn@google.com571c70b2013-07-10 17:09:50 +0000772 SkASSERT(fObjectType == kInteger_PdfObjectType);
773
774 if (fObjectType != kInteger_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000775 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000776 return 0;
777 }
778 return fIntegerValue;
779 }
780private:
781 inline double realValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000782 SkPdfMarkObjectUsed();
783
edisonn@google.com571c70b2013-07-10 17:09:50 +0000784 SkASSERT(fObjectType == kReal_PdfObjectType);
785
786 if (fObjectType != kReal_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000787 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000788 return 0;
789 }
790 return fRealValue;
791 }
792public:
793 inline double numberValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000794 SkPdfMarkObjectUsed();
795
edisonn@google.com571c70b2013-07-10 17:09:50 +0000796 SkASSERT(isNumber());
797
798 if (!isNumber()) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000799 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000800 return 0;
801 }
802 return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue;
803 }
804
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000805 inline SkScalar scalarValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000806 SkPdfMarkObjectUsed();
807
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000808 SkASSERT(isNumber());
809
810 if (!isNumber()) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000811 // TODO(edisonn): report/warn/assert.
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000812 return SkIntToScalar(0);
813 }
814 return fObjectType == kReal_PdfObjectType ? SkDoubleToScalar(fRealValue) :
815 SkIntToScalar(fIntegerValue);
816 }
817
edisonn@google.com571c70b2013-07-10 17:09:50 +0000818 int referenceId() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000819 SkPdfMarkObjectUsed();
820
edisonn@google.com571c70b2013-07-10 17:09:50 +0000821 SkASSERT(fObjectType == kReference_PdfObjectType);
822 return fRef.fId;
823 }
824
825 int referenceGeneration() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000826 SkPdfMarkObjectUsed();
827
edisonn@google.com571c70b2013-07-10 17:09:50 +0000828 SkASSERT(fObjectType == kReference_PdfObjectType);
829 return fRef.fGen;
830 }
831
832 inline const char* nameValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000833 SkPdfMarkObjectUsed();
834
edisonn@google.com571c70b2013-07-10 17:09:50 +0000835 SkASSERT(fObjectType == kName_PdfObjectType);
836
837 if (fObjectType != kName_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000838 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000839 return "";
840 }
841 return (const char*)fStr.fBuffer;
842 }
843
844 inline const char* stringValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000845 SkPdfMarkObjectUsed();
846
edisonn@google.com571c70b2013-07-10 17:09:50 +0000847 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
848
849 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000850 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000851 return "";
852 }
853 return (const char*)fStr.fBuffer;
854 }
855
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000856 inline NotOwnedString strRef() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000857 SkPdfMarkObjectUsed();
858
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000859 switch (fObjectType) {
860 case kString_PdfObjectType:
861 case kHexString_PdfObjectType:
862 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000863 case kName_PdfObjectType:
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000864 return fStr;
865
866 default:
867 // TODO(edisonn): report/warning
868 return NotOwnedString();
869 }
870 }
871
edisonn@google.com571c70b2013-07-10 17:09:50 +0000872 // TODO(edisonn): nameValue2 and stringValue2 are used to make code generation easy,
873 // but it is not a performat way to do it, since it will create an extra copy
874 // remove these functions and make code generated faster
edisonn@google.com063d7072013-08-16 15:05:08 +0000875 inline SkString nameValue2() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000876 SkPdfMarkObjectUsed();
877
edisonn@google.com571c70b2013-07-10 17:09:50 +0000878 SkASSERT(fObjectType == kName_PdfObjectType);
879
880 if (fObjectType != kName_PdfObjectType) {
881 // TODO(edisonn): log err
edisonn@google.com063d7072013-08-16 15:05:08 +0000882 return SkString();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000883 }
edisonn@google.com063d7072013-08-16 15:05:08 +0000884 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000885 }
886
edisonn@google.com063d7072013-08-16 15:05:08 +0000887 inline SkString stringValue2() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000888 SkPdfMarkObjectUsed();
889
edisonn@google.com571c70b2013-07-10 17:09:50 +0000890 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
891
892 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000893 // TODO(edisonn): report/warn/assert.
edisonn@google.com063d7072013-08-16 15:05:08 +0000894 return SkString();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000895 }
edisonn@google.com063d7072013-08-16 15:05:08 +0000896 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000897 }
898
899 inline bool boolValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000900 SkPdfMarkObjectUsed();
901
edisonn@google.com571c70b2013-07-10 17:09:50 +0000902 SkASSERT(fObjectType == kBoolean_PdfObjectType);
903
edisonn@google.comf111a4b2013-07-31 18:22:36 +0000904 if (fObjectType != kBoolean_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000905 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000906 return false;
907 }
908 return fBooleanValue;
909 }
910
911 SkRect rectangleValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000912 SkPdfMarkObjectUsed();
913
edisonn@google.com571c70b2013-07-10 17:09:50 +0000914 SkASSERT(isRectangle());
915 if (!isRectangle()) {
916 return SkRect::MakeEmpty();
917 }
918
919 double array[4];
920 for (int i = 0; i < 4; i++) {
921 // TODO(edisonn): version where we could resolve references?
edisonn@google.com3aa35552013-08-14 18:26:20 +0000922 const SkPdfNativeObject* elem = objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000923 if (elem == NULL || !elem->isNumber()) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000924 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000925 return SkRect::MakeEmpty();
926 }
927 array[i] = elem->numberValue();
928 }
929
930 return SkRect::MakeLTRB(SkDoubleToScalar(array[0]),
931 SkDoubleToScalar(array[1]),
932 SkDoubleToScalar(array[2]),
933 SkDoubleToScalar(array[3]));
934 }
935
936 SkMatrix matrixValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000937 SkPdfMarkObjectUsed();
938
edisonn@google.com571c70b2013-07-10 17:09:50 +0000939 SkASSERT(isMatrix());
940 if (!isMatrix()) {
941 return SkMatrix::I();
942 }
943
944 double array[6];
945 for (int i = 0; i < 6; i++) {
946 // TODO(edisonn): version where we could resolve references?
edisonn@google.com3aa35552013-08-14 18:26:20 +0000947 const SkPdfNativeObject* elem = objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000948 if (elem == NULL || !elem->isNumber()) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000949 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000950 return SkMatrix::I();
951 }
952 array[i] = elem->numberValue();
953 }
954
955 return SkMatrixFromPdfMatrix(array);
956 }
957
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000958 bool filterStream();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000959
960
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000961 bool GetFilteredStreamRef(unsigned char const** buffer, size_t* len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000962 SkPdfMarkObjectUsed();
963
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000964 // TODO(edisonn): add params that could let the last filter in place
965 // if it is jpeg or png to fast load images.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000966 if (!hasStream()) {
967 return false;
968 }
969
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000970 filterStream();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000971
972 if (buffer) {
973 *buffer = fStr.fBuffer;
974 }
975
976 if (len) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000977 *len = fStr.fBytes >> 2; // last 2 bits - TODO(edisonn): clean up.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000978 }
979
980 return true;
981 }
982
983 bool isStreamFiltered() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000984 SkPdfMarkObjectUsed();
985
edisonn@google.com571c70b2013-07-10 17:09:50 +0000986 return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit);
987 }
988
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000989 bool isStreamOwned() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000990 SkPdfMarkObjectUsed();
991
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000992 return hasStream() && ((fStr.fBytes & 2) == kOwnedStreamBit);
993 }
994
995 bool GetUnfilteredStreamRef(unsigned char const** buffer, size_t* len) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000996 SkPdfMarkObjectUsed();
997
edisonn@google.com571c70b2013-07-10 17:09:50 +0000998 if (isStreamFiltered()) {
999 return false;
1000 }
1001
1002 if (!hasStream()) {
1003 return false;
1004 }
1005
1006 if (buffer) {
1007 *buffer = fStr.fBuffer;
1008 }
1009
1010 if (len) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001011 *len = fStr.fBytes >> 2; // remove last 2 bits - TODO(edisonn): clean up.
edisonn@google.com571c70b2013-07-10 17:09:50 +00001012 }
1013
1014 return true;
1015 }
1016
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001017 bool addStream(const unsigned char* buffer, size_t len) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001018 SkPdfMarkObjectUsed();
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001019
edisonn@google.com571c70b2013-07-10 17:09:50 +00001020 SkASSERT(!hasStream());
1021 SkASSERT(isDictionary());
1022
1023 if (!isDictionary() || hasStream()) {
1024 return false;
1025 }
1026
1027 fStr.fBuffer = buffer;
1028 fStr.fBytes = (len << 2) + kUnfilteredStreamBit;
1029
1030 return true;
1031 }
1032
edisonn@google.com276fed92013-08-01 21:20:47 +00001033 static void appendSpaces(SkString* str, int level) {
edisonn@google.com9a43c182013-08-01 20:06:42 +00001034 for (int i = 0 ; i < level; i++) {
1035 str->append(" ");
1036 }
1037 }
1038
edisonn@google.com3aa35552013-08-14 18:26:20 +00001039 static void append(SkString* str, const char* data, size_t len, const char* prefix = "\\x") {
1040 for (unsigned int i = 0 ; i < len; i++) {
1041 if (data[i] == kNUL_PdfWhiteSpace) {
1042 str->append(prefix);
1043 str->append("00");
1044 } else if (data[i] == kHT_PdfWhiteSpace) {
1045 str->append(prefix);
1046 str->append("09");
1047 } else if (data[i] == kLF_PdfWhiteSpace) {
1048 str->append(prefix);
1049 str->append("0A");
1050 } else if (data[i] == kFF_PdfWhiteSpace) {
1051 str->append(prefix);
1052 str->append("0C");
1053 } else if (data[i] == kCR_PdfWhiteSpace) {
1054 str->append(prefix);
1055 str->append("0D");
1056 } else {
1057 str->append(data + i, 1);
1058 }
1059 }
1060 }
1061
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001062 SkString toString(int firstRowLevel = 0, int level = 0) {
edisonn@google.com571c70b2013-07-10 17:09:50 +00001063 SkString str;
edisonn@google.com9a43c182013-08-01 20:06:42 +00001064 appendSpaces(&str, firstRowLevel);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001065 switch (fObjectType) {
1066 case kInvalid_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001067 str.append("__Invalid");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001068 break;
1069
1070 case kBoolean_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001071 str.appendf("%s", fBooleanValue ? "true" : "false");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001072 break;
1073
1074 case kInteger_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001075 str.appendf("%i", (int)fIntegerValue);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001076 break;
1077
1078 case kReal_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001079 str.appendf("%f", fRealValue);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001080 break;
1081
1082 case kString_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001083 str.append("\"");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001084 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com9a43c182013-08-01 20:06:42 +00001085 str.append("\"");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001086 break;
1087
1088 case kHexString_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001089 str.append("<");
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001090 for (unsigned int i = 0 ; i < fStr.fBytes; i++) {
1091 str.appendf("%02x", (unsigned int)fStr.fBuffer[i]);
1092 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001093 str.append(">");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001094 break;
1095
1096 case kName_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001097 str.append("/");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001098 append(&str, (const char*)fStr.fBuffer, fStr.fBytes, "#");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001099 break;
1100
1101 case kKeyword_PdfObjectType:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001102 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001103 break;
1104
1105 case kArray_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001106 str.append("[\n");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001107 for (unsigned int i = 0; i < size(); i++) {
edisonn@google.com9a43c182013-08-01 20:06:42 +00001108 str.append(objAtAIndex(i)->toString(level + 1, level + 1));
1109 if (i < size() - 1) {
1110 str.append(",");
1111 }
1112 str.append("\n");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001113 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001114 appendSpaces(&str, level);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001115 str.append("]");
1116 break;
1117
edisonn@google.com9a43c182013-08-01 20:06:42 +00001118 case kDictionary_PdfObjectType: {
edisonn@google.com3aa35552013-08-14 18:26:20 +00001119 SkTDict<SkPdfNativeObject*>::Iter iter(*fMap);
1120 SkPdfNativeObject* obj = NULL;
edisonn@google.com9a43c182013-08-01 20:06:42 +00001121 const char* key = NULL;
1122 str.append("<<\n");
1123 while ((key = iter.next(&obj)) != NULL) {
1124 appendSpaces(&str, level + 2);
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001125 str.appendf("/%s %s\n", key,
1126 obj->toString(0, level + strlen(key) + 4).c_str());
edisonn@google.com9a43c182013-08-01 20:06:42 +00001127 }
1128 appendSpaces(&str, level);
1129 str.append(">>");
1130 if (hasStream()) {
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001131 const unsigned char* stream = NULL;
1132 size_t length = 0;
1133 if (GetFilteredStreamRef(&stream, &length)) {
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001134 str.append("stream\n");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001135 append(&str, (const char*)stream, length > 256 ? 256 : length);
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001136 str.append("\nendstream");
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001137 } else {
1138 str.append("stream STREAM_ERROR endstream");
1139 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001140 }
edisonn@google.com571c70b2013-07-10 17:09:50 +00001141 }
1142 break;
1143
1144 case kNull_PdfObjectType:
1145 str = "NULL";
1146 break;
1147
1148 case kReference_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001149 str.appendf("%i %i R", fRef.fId, fRef.fGen);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001150 break;
1151
1152 case kUndefined_PdfObjectType:
1153 str = "Undefined";
1154 break;
1155
1156 default:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001157 str = "Error";
edisonn@google.com571c70b2013-07-10 17:09:50 +00001158 break;
1159 }
1160
1161 return str;
1162 }
1163
1164private:
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001165 static void makeStringCore(const unsigned char* start, SkPdfNativeObject* obj,
1166 ObjectType type) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001167 makeStringCore(start, strlen((const char*)start), obj, type);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001168 }
1169
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001170 static void makeStringCore(const unsigned char* start, const unsigned char* end,
1171 SkPdfNativeObject* obj, ObjectType type) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001172 makeStringCore(start, end - start, obj, type);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001173 }
1174
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001175 static void makeStringCore(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj,
1176 ObjectType type) {
edisonn@google.com571c70b2013-07-10 17:09:50 +00001177 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
1178
1179 obj->fObjectType = type;
1180 obj->fStr.fBuffer = start;
1181 obj->fStr.fBytes = bytes;
1182 }
1183
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001184 bool applyFilter(const char* name);
1185 bool applyFlateDecodeFilter();
1186 bool applyDCTDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +00001187};
1188
edisonn@google.com3aa35552013-08-14 18:26:20 +00001189class SkPdfStream : public SkPdfNativeObject {};
1190class SkPdfArray : public SkPdfNativeObject {};
1191class SkPdfString : public SkPdfNativeObject {};
1192class SkPdfHexString : public SkPdfNativeObject {};
1193class SkPdfInteger : public SkPdfNativeObject {};
1194class SkPdfReal : public SkPdfNativeObject {};
1195class SkPdfNumber : public SkPdfNativeObject {};
edisonn@google.com571c70b2013-07-10 17:09:50 +00001196
edisonn@google.com3aa35552013-08-14 18:26:20 +00001197class SkPdfName : public SkPdfNativeObject {
1198 SkPdfName() : SkPdfNativeObject() {
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001199 SkPdfNativeObject::makeName((const unsigned char*)"", this);
edisonn@google.com78b38b12013-07-15 18:20:58 +00001200 }
1201public:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001202 SkPdfName(char* name) : SkPdfNativeObject() {
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001203 this->makeName((const unsigned char*)name, this);
edisonn@google.com78b38b12013-07-15 18:20:58 +00001204 }
1205};
1206
edisonn@google.comcf2cfa12013-08-21 16:31:37 +00001207#endif // SkPdfNativeObject