blob: 6ce5622fee6fd5c75aeff0caf7f8a896222d2a00 [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.com2af2ad92013-10-11 16:17:44 +000033/** \class SkPdfNativeObject
34 *
35 * The SkPdfNativeObject class is used to store a pdf object. Classes that inherit it are not
36 * allowed to add fields.
37 *
38 * SkPdfAllocator will allocate them in chunks and will free them in destructor.
39 *
40 * You can allocate one on the stack, as long as you call reset() at the end, and any objects it
41 * points to in an allocator. But if your object is a simple one, like number, then
42 * putting it on stack will be just fine.
43 *
44 */
edisonn@google.com3aa35552013-08-14 18:26:20 +000045class SkPdfNativeObject {
edisonn@google.com571c70b2013-07-10 17:09:50 +000046 public:
47 enum ObjectType {
edisonn@google.comaf54a512013-09-13 19:33:42 +000048 // The type will have only one of these values, but for error reporting, we make it an enum
49 // so it can easily report that something was expected to be one of a few types
50 kInvalid_PdfObjectType = 1 << 1,
edisonn@google.com571c70b2013-07-10 17:09:50 +000051
edisonn@google.comaf54a512013-09-13 19:33:42 +000052 kBoolean_PdfObjectType = 1 << 2,
53 kInteger_PdfObjectType = 1 << 3,
54 kReal_PdfObjectType = 1 << 4,
55 _kNumber_PdfObjectType = kInteger_PdfObjectType | kReal_PdfObjectType,
56 kString_PdfObjectType = 1 << 5,
57 kHexString_PdfObjectType = 1 << 6,
58 _kAnyString_PdfObjectType = kString_PdfObjectType | kHexString_PdfObjectType,
59 kName_PdfObjectType = 1 << 7,
60 kKeyword_PdfObjectType = 1 << 8,
61 _kStream_PdfObjectType = 1 << 9, // attached to a Dictionary, do not use
62 kArray_PdfObjectType = 1 << 10,
63 kDictionary_PdfObjectType = 1 << 11,
64 kNull_PdfObjectType = 1 << 12,
edisonn@google.com571c70b2013-07-10 17:09:50 +000065
edisonn@google.comaf54a512013-09-13 19:33:42 +000066 kReference_PdfObjectType = 1 << 13,
edisonn@google.com571c70b2013-07-10 17:09:50 +000067
edisonn@google.comc8fda9d2013-10-09 20:23:12 +000068 kUndefined_PdfObjectType = 1 << 14, // per 1.4 spec, if the same key appear twice in the
69 // dictionary, the value is undefined.
edisonn@google.comaf54a512013-09-13 19:33:42 +000070
71 _kObject_PdfObjectType = -1,
edisonn@google.com571c70b2013-07-10 17:09:50 +000072 };
73
edisonn@google.comb0145ce2013-08-05 16:23:23 +000074 enum DataType {
75 kEmpty_Data,
76 kFont_Data,
77 kBitmap_Data,
78 };
79
edisonn@google.com571c70b2013-07-10 17:09:50 +000080private:
edisonn@google.comc8fda9d2013-10-09 20:23:12 +000081 // TODO(edisonn): assert reset operations while in rendering! The objects should be reset
82 // only when rendering is completed.
edisonn@google.com063d7072013-08-16 15:05:08 +000083 uint32_t fInRendering : 1;
84 uint32_t fUnused : 31;
85
edisonn@google.com571c70b2013-07-10 17:09:50 +000086 struct Reference {
87 unsigned int fId;
88 unsigned int fGen;
89 };
90
edisonn@google.com571c70b2013-07-10 17:09:50 +000091 ObjectType fObjectType;
92
93 union {
94 bool fBooleanValue;
95 int64_t fIntegerValue;
edisonn@google.comc8fda9d2013-10-09 20:23:12 +000096 // TODO(edisonn): double, float, SkScalar?
edisonn@google.com571c70b2013-07-10 17:09:50 +000097 double fRealValue;
98 NotOwnedString fStr;
99
edisonn@google.com3aa35552013-08-14 18:26:20 +0000100 SkTDArray<SkPdfNativeObject*>* fArray;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000101 Reference fRef;
102 };
edisonn@google.com3aa35552013-08-14 18:26:20 +0000103 SkTDict<SkPdfNativeObject*>* fMap;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000104
105 // TODO(edisonn): rename data with cache
edisonn@google.com571c70b2013-07-10 17:09:50 +0000106 void* fData;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000107 DataType fDataType;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000108
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000109#ifdef PDF_TRACK_OBJECT_USAGE
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000110 // Records if the object was used during rendering/proccessing. It can be used to track
111 // what features are only partially implemented, by looking at what objects have not been
112 // accessed.
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000113 mutable bool fUsed;
114#endif // PDF_TRACK_OBJECT_USAGE
115
edisonn@google.combca421b2013-09-05 20:00:21 +0000116#ifdef PDF_TRACK_STREAM_OFFSETS
edisonn@google.com571c70b2013-07-10 17:09:50 +0000117public:
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000118 // TODO(edisonn): replace them with char* start, end - and a mechanism to register streams.
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
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000127 // TODO(edisonn): remove these ones.
edisonn@google.combca421b2013-09-05 20:00:21 +0000128 int streamId() const { return fStreamId; }
129 int offsetStart() const { return fOffsetStart; }
130 int offsetEnd() const { return fOffsetEnd; }
131#endif // PDF_TRACK_STREAM_OFFSETS
132
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.com2af2ad92013-10-11 16:17:44 +0000149 // Used to verify if a form is used in rendering, to check for infinite loops.
edisonn@google.com063d7072013-08-16 15:05:08 +0000150 bool inRendering() const { return fInRendering != 0; }
151 void startRendering() {fInRendering = 1;}
152 void doneRendering() {fInRendering = 0;}
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000153
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000154 // Each object can cache one entry associated with it.
155 // for example a SkPdfImage could cache an SkBitmap, of a SkPdfFont, could cache a SkTypeface.
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000156 inline bool hasData(DataType type) {
157 return type == fDataType;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000158 }
159
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000160 // returns the cached value
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000161 inline void* data(DataType type) {
162 return type == fDataType ? fData : NULL;
163 }
164
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000165 // Stores something in the cache
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000166 inline void setData(void* data, DataType type) {
167 releaseData();
168 fDataType = type;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000169 fData = data;
170 }
171
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000172 // destroys the cache
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000173 void releaseData();
174
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000175 // TODO(edisonn): add an assert that reset was called
edisonn@google.com3aa35552013-08-14 18:26:20 +0000176// ~SkPdfNativeObject() {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000177// //reset(); must be called manually! Normally, will be called by allocator destructor.
edisonn@google.com222382b2013-07-10 22:33:10 +0000178// }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000179
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000180 // Resets a pdf object, deleting all resources directly referenced.
181 // It will not reset/delete indirect resources.
182 // (e.g. it deletes only the array holding pointers to objects, but does not del the objects)
edisonn@google.com571c70b2013-07-10 17:09:50 +0000183 void reset() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000184 SkPdfMarkObjectUnused();
185
edisonn@google.com571c70b2013-07-10 17:09:50 +0000186 switch (fObjectType) {
187 case kArray_PdfObjectType:
188 delete fArray;
189 break;
190
191 case kDictionary_PdfObjectType:
192 delete fMap;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000193 if (isStreamOwned()) {
194 delete[] fStr.fBuffer;
195 fStr.fBuffer = NULL;
196 fStr.fBytes = 0;
197 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000198 break;
199
200 default:
201 break;
202 }
203 fObjectType = kInvalid_PdfObjectType;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000204 releaseData();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000205 }
206
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000207 // returns the object type (Null, Integer, String, Dictionary, ... )
208 // It does not specify what type of dictionary we have.
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000209 ObjectType type() {
210 SkPdfMarkObjectUsed();
211
212 return fObjectType;
213 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000214
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000215 // Gives quick access to the buffer's address of a string/keyword/name
edisonn@google.com571c70b2013-07-10 17:09:50 +0000216 const char* c_str() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000217 SkPdfMarkObjectUsed();
218
edisonn@google.com571c70b2013-07-10 17:09:50 +0000219 switch (fObjectType) {
220 case kString_PdfObjectType:
221 case kHexString_PdfObjectType:
222 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000223 case kName_PdfObjectType:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000224 return (const char*)fStr.fBuffer;
225
226 default:
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000227 // TODO(edisonn): report/warning/assert?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000228 return NULL;
229 }
230 }
231
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000232 // Gives quick access to the length of a string/keyword/name
edisonn@google.come878e722013-07-29 19:10:58 +0000233 size_t lenstr() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000234 SkPdfMarkObjectUsed();
235
edisonn@google.com571c70b2013-07-10 17:09:50 +0000236 switch (fObjectType) {
237 case kString_PdfObjectType:
238 case kHexString_PdfObjectType:
239 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000240 case kName_PdfObjectType:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000241 return fStr.fBytes;
242
243 default:
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000244 // TODO(edisonn): report/warning/assert?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000245 return 0;
246 }
247 }
248
249
250 // TODO(edisonn): NYI
251 SkPdfDate& dateValue() const {
252 static SkPdfDate nyi;
253 return nyi;
254 }
255
256 // TODO(edisonn): NYI
257 SkPdfFunction& functionValue() const {
258 static SkPdfFunction nyi;
259 return nyi;
260 }
261
262 // TODO(edisonn): NYI
263 SkPdfFileSpec& fileSpecValue() const {
264 static SkPdfFileSpec nyi;
265 return nyi;
266 }
267
268 // TODO(edisonn): NYI
269 SkPdfTree& treeValue() const {
270 static SkPdfTree nyi;
271 return nyi;
272 }
273
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000274 // Creates a Boolean object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000275 static void makeBoolean(bool value, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000276 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
277
278 obj->fObjectType = kBoolean_PdfObjectType;
279 obj->fBooleanValue = value;
280 }
281
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000282 static SkPdfNativeObject makeBoolean(bool value) {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000283 SkPdfNativeObject obj;
edisonn@google.combca421b2013-09-05 20:00:21 +0000284
edisonn@google.com571c70b2013-07-10 17:09:50 +0000285 obj.fObjectType = kBoolean_PdfObjectType;
286 obj.fBooleanValue = value;
287 return obj;
288 }
289
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000290 // Creates an Integer object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000291 static void makeInteger(int64_t value, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000292 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
293
294 obj->fObjectType = kInteger_PdfObjectType;
295 obj->fIntegerValue = value;
296 }
297
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000298 // Creates a Real object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000299 static void makeReal(double value, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000300 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
301
302 obj->fObjectType = kReal_PdfObjectType;
303 obj->fRealValue = value;
304 }
305
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000306 // Creates a Null object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000307 static void makeNull(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000308 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
309
310 obj->fObjectType = kNull_PdfObjectType;
311 }
312
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000313 static SkPdfNativeObject makeNull() {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000314 SkPdfNativeObject obj;
edisonn@google.combca421b2013-09-05 20:00:21 +0000315
edisonn@google.com571c70b2013-07-10 17:09:50 +0000316 obj.fObjectType = kNull_PdfObjectType;
317 return obj;
318 }
319
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000320 // TODO(edisonn): this might not woirk well in Chrome
edisonn@google.com3aa35552013-08-14 18:26:20 +0000321 static SkPdfNativeObject kNull;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000322
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000323 // Creates a Numeric object from a string. Assumes and asserts that it was never initialized.
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000324 static void makeNumeric(const unsigned char* start, const unsigned char* end,
325 SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000326 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
327
328 // TODO(edisonn): NYI properly
329 // if has dot (impl), or exceeds max int, is real, otherwise is int
330 bool isInt = true;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000331 for (const unsigned char* current = start; current < end; current++) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000332 if (*current == '.') {
333 isInt = false;
334 break;
335 }
336 // TODO(edisonn): report parse issue with numbers like "24asdasd123"
337 }
338 if (isInt) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000339 makeInteger(atol((const char*)start), obj);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000340 } else {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000341 makeReal(atof((const char*)start), obj);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000342 }
343 }
344
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000345 // Creates a Reference object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000346 static void makeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000347 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
348
349 obj->fObjectType = kReference_PdfObjectType;
350 obj->fRef.fId = id;
351 obj->fRef.fGen = gen;
352 }
353
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000354 // Creates a Reference object. Resets the object before use.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000355 static void resetAndMakeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj) {
edisonn@google.combca421b2013-09-05 20:00:21 +0000356 obj->reset();
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000357 makeReference(id, gen, obj);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000358 }
359
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000360 // Creates a String object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000361 static void makeString(const unsigned char* start, SkPdfNativeObject* obj) {
362 makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000363 }
364
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000365 // Creates a String object. Assumes and asserts that it was never initialized.
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000366 static void makeString(const unsigned char* start, const unsigned char* end,
367 SkPdfNativeObject* obj) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000368 makeStringCore(start, end - start, obj, kString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000369 }
370
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000371 // Creates a String object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000372 static void makeString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
373 makeStringCore(start, bytes, obj, kString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000374 }
375
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000376 // Creates a HexString object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000377 static void makeHexString(const unsigned char* start, SkPdfNativeObject* obj) {
378 makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000379 }
380
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000381 // Creates a HexString object. Assumes and asserts that it was never initialized.
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000382 static void makeHexString(const unsigned char* start, const unsigned char* end,
383 SkPdfNativeObject* obj) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000384 makeStringCore(start, end - start, obj, kHexString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000385 }
386
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000387 // Creates a HexString object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000388 static void makeHexString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
389 makeStringCore(start, bytes, obj, kHexString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000390 }
391
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000392 // Creates a Name object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000393 static void makeName(const unsigned char* start, SkPdfNativeObject* obj) {
394 makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000395 }
396
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000397 // Creates a Name object. Assumes and asserts that it was never initialized.
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000398 static void makeName(const unsigned char* start, const unsigned char* end,
399 SkPdfNativeObject* obj) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000400 makeStringCore(start, end - start, obj, kName_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000401 }
402
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000403 // Creates a Name object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000404 static void makeName(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
405 makeStringCore(start, bytes, obj, kName_PdfObjectType);
edisonn@google.combca421b2013-09-05 20:00:21 +0000406 }
407
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000408 // Creates a Keyword object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000409 static void makeKeyword(const unsigned char* start, SkPdfNativeObject* obj) {
410 makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType);
edisonn@google.combca421b2013-09-05 20:00:21 +0000411 }
412
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000413 // Creates a Keyword object. Assumes and asserts that it was never initialized.
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000414 static void makeKeyword(const unsigned char* start, const unsigned char* end,
415 SkPdfNativeObject* obj) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000416 makeStringCore(start, end - start, obj, kKeyword_PdfObjectType);
edisonn@google.combca421b2013-09-05 20:00:21 +0000417 }
418
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000419 // Creates a Keyword object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000420 static void makeKeyword(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
421 makeStringCore(start, bytes, obj, kKeyword_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000422 }
423
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000424 // Creates an empty Array object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000425 static void makeEmptyArray(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000426 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
427
428 obj->fObjectType = kArray_PdfObjectType;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000429 obj->fArray = new SkTDArray<SkPdfNativeObject*>();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000430 }
431
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000432 // Appends an object into the array. Assumes <this> is an array.
edisonn@google.com3aa35552013-08-14 18:26:20 +0000433 bool appendInArray(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000434 SkASSERT(fObjectType == kArray_PdfObjectType);
435 if (fObjectType != kArray_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000436 // TODO(edisonn): report/warning/assert?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000437 return false;
438 }
439
440 fArray->push(obj);
441 return true;
442 }
443
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000444 // Returns the size of an array.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000445 size_t size() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000446 SkPdfMarkObjectUsed();
447
edisonn@google.com571c70b2013-07-10 17:09:50 +0000448 SkASSERT(fObjectType == kArray_PdfObjectType);
449
450 return fArray->count();
451 }
452
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000453 // Returns one object of an array, by index.
edisonn@google.com3aa35552013-08-14 18:26:20 +0000454 SkPdfNativeObject* objAtAIndex(int i) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000455 SkPdfMarkObjectUsed();
456
edisonn@google.com571c70b2013-07-10 17:09:50 +0000457 SkASSERT(fObjectType == kArray_PdfObjectType);
458
459 return (*fArray)[i];
460 }
461
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000462 // Returns one object of an array, by index.
edisonn@google.com3aa35552013-08-14 18:26:20 +0000463 const SkPdfNativeObject* objAtAIndex(int i) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000464 SkPdfMarkObjectUsed();
465
edisonn@google.com571c70b2013-07-10 17:09:50 +0000466 SkASSERT(fObjectType == kArray_PdfObjectType);
467
468 return (*fArray)[i];
469 }
470
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000471 // Returns one object of an array, by index.
edisonn@google.com3aa35552013-08-14 18:26:20 +0000472 SkPdfNativeObject* operator[](int i) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000473 SkPdfMarkObjectUsed();
474
edisonn@google.com571c70b2013-07-10 17:09:50 +0000475 SkASSERT(fObjectType == kArray_PdfObjectType);
476
477 return (*fArray)[i];
478 }
479
edisonn@google.com3aa35552013-08-14 18:26:20 +0000480 const SkPdfNativeObject* operator[](int i) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000481 SkPdfMarkObjectUsed();
482
edisonn@google.com571c70b2013-07-10 17:09:50 +0000483 SkASSERT(fObjectType == kArray_PdfObjectType);
484
485 return (*fArray)[i];
486 }
487
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000488 // Removes the last object in the array.
489 SkPdfNativeObject* removeLastInArray() {
490 SkPdfMarkObjectUsed();
491
492 SkASSERT(fObjectType == kArray_PdfObjectType);
493
494 SkPdfNativeObject* ret = NULL;
495 fArray->pop(&ret);
496
497 return ret;
498 }
499
500 // Creates an empty Dictionary object. Assumes and asserts that it was never initialized.
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000501 static void makeEmptyDictionary(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000502 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
503
504 obj->fObjectType = kDictionary_PdfObjectType;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000505 obj->fMap = new SkTDict<SkPdfNativeObject*>(1);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000506 obj->fStr.fBuffer = NULL;
507 obj->fStr.fBytes = 0;
508 }
509
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000510 // TODO(edisonn): perf: get all the possible names from spec, and compute a hash function
edisonn@google.com571c70b2013-07-10 17:09:50 +0000511 // that would create no overlaps in the same dictionary
512 // or build a tree of chars that when followed goes to a unique id/index/hash
513 // TODO(edisonn): generate constants like kDictFoo, kNameDict_name
514 // which will be used in code
515 // add function SkPdfFastNameKey key(const char* key);
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000516 // TODO(edisonn): setting the same key twice, will make the value undefined!
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000517
518 // this[key] = value;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000519 bool set(const SkPdfNativeObject* key, SkPdfNativeObject* value) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000520 SkPdfMarkObjectUsed();
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000521
edisonn@google.com571c70b2013-07-10 17:09:50 +0000522 SkASSERT(fObjectType == kDictionary_PdfObjectType);
523 SkASSERT(key->fObjectType == kName_PdfObjectType);
524
525 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000526 // TODO(edisonn): report/warn/assert?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000527 return false;
528 }
529
edisonn@google.comd761e322013-07-22 17:29:43 +0000530 return set(key->fStr.fBuffer, key->fStr.fBytes, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000531 }
532
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000533 // this[key] = value;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000534 bool set(const char* key, SkPdfNativeObject* value) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000535 SkPdfMarkObjectUsed();
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000536
edisonn@google.comd761e322013-07-22 17:29:43 +0000537 return set((const unsigned char*)key, strlen(key), value);
538 }
539
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000540 // this[key] = value;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000541 bool set(const unsigned char* key, size_t len, SkPdfNativeObject* value) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000542 SkPdfMarkObjectUsed();
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000543
edisonn@google.com571c70b2013-07-10 17:09:50 +0000544 SkASSERT(fObjectType == kDictionary_PdfObjectType);
545
546 if (fObjectType != kDictionary_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000547 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000548 return false;
549 }
550
edisonn@google.comd761e322013-07-22 17:29:43 +0000551 return fMap->set((const char*)key, len, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000552 }
553
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000554 // Returns an object from a Dictionary, identified by it's name.
edisonn@google.com3aa35552013-08-14 18:26:20 +0000555 SkPdfNativeObject* get(const SkPdfNativeObject* key) {
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->fObjectType == kName_PdfObjectType);
560
561 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000562 // TODO(edisonn): report/warn/assert.
edisonn@google.com3fc48262013-07-22 15:29:55 +0000563 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000564 }
565
edisonn@google.comd761e322013-07-22 17:29:43 +0000566 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000567 }
568
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000569 // Returns an object from a Dictionary, identified by it's name.
edisonn@google.com3aa35552013-08-14 18:26:20 +0000570 SkPdfNativeObject* get(const char* key) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000571 SkPdfMarkObjectUsed();
572
edisonn@google.comd761e322013-07-22 17:29:43 +0000573 return get((const unsigned char*)key, strlen(key));
574 }
575
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000576 // Returns an object from a Dictionary, identified by it's name.
edisonn@google.com3aa35552013-08-14 18:26:20 +0000577 SkPdfNativeObject* get(const unsigned char* key, size_t len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000578 SkPdfMarkObjectUsed();
579
edisonn@google.com571c70b2013-07-10 17:09:50 +0000580 SkASSERT(fObjectType == kDictionary_PdfObjectType);
581 SkASSERT(key);
582 if (fObjectType != kDictionary_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000583 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000584 return NULL;
585 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000586 SkPdfNativeObject* ret = NULL;
edisonn@google.comd761e322013-07-22 17:29:43 +0000587 fMap->find((const char*)key, len, &ret);
edisonn@google.com9a43c182013-08-01 20:06:42 +0000588
589#ifdef PDF_TRACE
590 SkString _key;
591 _key.append((const char*)key, len);
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000592 printf("\nget(/%s) = %s\n", _key.c_str(),
593 ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
edisonn@google.com9a43c182013-08-01 20:06:42 +0000594#endif
595
edisonn@google.com571c70b2013-07-10 17:09:50 +0000596 return ret;
597 }
598
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000599 // Returns an object from a Dictionary, identified by it's name.
edisonn@google.com3aa35552013-08-14 18:26:20 +0000600 const SkPdfNativeObject* get(const SkPdfNativeObject* key) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000601 SkPdfMarkObjectUsed();
602
edisonn@google.com571c70b2013-07-10 17:09:50 +0000603 SkASSERT(fObjectType == kDictionary_PdfObjectType);
604 SkASSERT(key->fObjectType == kName_PdfObjectType);
605
606 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000607 // TODO(edisonn): report/warn/assert.
edisonn@google.com3fc48262013-07-22 15:29:55 +0000608 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000609 }
610
edisonn@google.comd761e322013-07-22 17:29:43 +0000611 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000612 }
613
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000614 // Returns an object from a Dictionary, identified by it's name.
edisonn@google.com3aa35552013-08-14 18:26:20 +0000615 const SkPdfNativeObject* get(const char* key) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000616 SkPdfMarkObjectUsed();
617
edisonn@google.comd761e322013-07-22 17:29:43 +0000618 return get((const unsigned char*)key, strlen(key));
619 }
620
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000621 // Returns an object from a Dictionary, identified by it's name.
edisonn@google.com3aa35552013-08-14 18:26:20 +0000622 const SkPdfNativeObject* get(const unsigned char* key, size_t len) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000623 SkPdfMarkObjectUsed();
624
edisonn@google.com571c70b2013-07-10 17:09:50 +0000625 SkASSERT(fObjectType == kDictionary_PdfObjectType);
626 SkASSERT(key);
627 if (fObjectType != kDictionary_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000628 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000629 return NULL;
630 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000631 SkPdfNativeObject* ret = NULL;
edisonn@google.comd761e322013-07-22 17:29:43 +0000632 fMap->find((const char*)key, len, &ret);
edisonn@google.com9a43c182013-08-01 20:06:42 +0000633
634#ifdef PDF_TRACE
635 SkString _key;
636 _key.append((const char*)key, len);
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000637 printf("\nget(/%s) = %s\n", _key.c_str(),
638 ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
edisonn@google.com9a43c182013-08-01 20:06:42 +0000639#endif
640
edisonn@google.com571c70b2013-07-10 17:09:50 +0000641 return ret;
642 }
643
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000644 // Returns an object from a Dictionary, identified by it's name.
edisonn@google.com3aa35552013-08-14 18:26:20 +0000645 const SkPdfNativeObject* get(const char* key, const char* abr) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000646 SkPdfMarkObjectUsed();
647
edisonn@google.com3aa35552013-08-14 18:26:20 +0000648 const SkPdfNativeObject* ret = get(key);
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000649 // TODO(edisonn): remove || *abr == '\0' and pass NULL in the _autogen files instead.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000650 if (ret != NULL || abr == NULL || *abr == '\0') {
651 return ret;
652 }
653 return get(abr);
654 }
655
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000656 // Returns an object from a Dictionary, identified by it's name.
edisonn@google.com3aa35552013-08-14 18:26:20 +0000657 SkPdfNativeObject* get(const char* key, const char* abr) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000658 SkPdfMarkObjectUsed();
659
edisonn@google.com3aa35552013-08-14 18:26:20 +0000660 SkPdfNativeObject* ret = get(key);
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000661 // TODO(edisonn): remove || *abr == '\0' and pass NULL in the _autogen files instead.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000662 if (ret != NULL || abr == NULL || *abr == '\0') {
663 return ret;
664 }
665 return get(abr);
666 }
667
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000668 // Casts the object to a Dictionary. Asserts if the object is not a Dictionary.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000669 SkPdfDictionary* asDictionary() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000670 SkPdfMarkObjectUsed();
671
edisonn@google.com571c70b2013-07-10 17:09:50 +0000672 SkASSERT(isDictionary());
673 if (!isDictionary()) {
674 return NULL;
675 }
676 return (SkPdfDictionary*) this;
677 }
678
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000679 // Casts the object to a Dictionary. Asserts if the object is not a Dictionary.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000680 const SkPdfDictionary* asDictionary() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000681 SkPdfMarkObjectUsed();
682
edisonn@google.com571c70b2013-07-10 17:09:50 +0000683 SkASSERT(isDictionary());
684 if (!isDictionary()) {
685 return NULL;
686 }
687 return (SkPdfDictionary*) this;
688 }
689
690
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000691 // Returns true if the object is a Reference.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000692 bool isReference() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000693 SkPdfMarkObjectUsed();
694
edisonn@google.com571c70b2013-07-10 17:09:50 +0000695 return fObjectType == kReference_PdfObjectType;
696 }
697
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000698 // Returns true if the object is a Boolean.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000699 bool isBoolean() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000700 SkPdfMarkObjectUsed();
701
edisonn@google.com571c70b2013-07-10 17:09:50 +0000702 return fObjectType == kBoolean_PdfObjectType;
703 }
704
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000705 // Returns true if the object is an Integer.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000706 bool isInteger() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000707 SkPdfMarkObjectUsed();
708
edisonn@google.com571c70b2013-07-10 17:09:50 +0000709 return fObjectType == kInteger_PdfObjectType;
710 }
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000711
edisonn@google.com571c70b2013-07-10 17:09:50 +0000712private:
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000713 // Returns true if the object is a Real number.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000714 bool isReal() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000715 SkPdfMarkObjectUsed();
716
edisonn@google.com571c70b2013-07-10 17:09:50 +0000717 return fObjectType == kReal_PdfObjectType;
718 }
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000719
edisonn@google.com571c70b2013-07-10 17:09:50 +0000720public:
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000721 // Returns true if the object is a Number (either Integer or Real).
edisonn@google.com571c70b2013-07-10 17:09:50 +0000722 bool isNumber() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000723 SkPdfMarkObjectUsed();
724
edisonn@google.com571c70b2013-07-10 17:09:50 +0000725 return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_PdfObjectType;
726 }
727
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000728 // Returns true if the object is a R keyword (used to identify references, e.g. "10 3 R".
edisonn@google.com571c70b2013-07-10 17:09:50 +0000729 bool isKeywordReference() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000730 SkPdfMarkObjectUsed();
731
edisonn@google.com571c70b2013-07-10 17:09:50 +0000732 return fObjectType == kKeyword_PdfObjectType && fStr.fBytes == 1 && fStr.fBuffer[0] == 'R';
733 }
734
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000735 // Returns true if the object is a Keyword.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000736 bool isKeyword() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000737 SkPdfMarkObjectUsed();
738
edisonn@google.com571c70b2013-07-10 17:09:50 +0000739 return fObjectType == kKeyword_PdfObjectType;
740 }
741
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000742 // Returns true if the object is a given Keyword.
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000743 bool isKeyword(const char* keyword) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000744 SkPdfMarkObjectUsed();
745
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000746 if (!isKeyword()) {
747 return false;
748 }
749
750 if (strlen(keyword) != fStr.fBytes) {
751 return false;
752 }
753
754 if (strncmp(keyword, (const char*)fStr.fBuffer, fStr.fBytes) != 0) {
755 return false;
756 }
757
758 return true;
759 }
760
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000761 // Returns true if the object is a Name.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000762 bool isName() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000763 SkPdfMarkObjectUsed();
764
edisonn@google.com571c70b2013-07-10 17:09:50 +0000765 return fObjectType == kName_PdfObjectType;
766 }
767
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000768 // Returns true if the object is a given Name.
edisonn@google.com78b38b12013-07-15 18:20:58 +0000769 bool isName(const char* name) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000770 SkPdfMarkObjectUsed();
771
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000772 return fObjectType == kName_PdfObjectType &&
773 fStr.fBytes == strlen(name) &&
774 strncmp((const char*)fStr.fBuffer, name, fStr.fBytes) == 0;
edisonn@google.com78b38b12013-07-15 18:20:58 +0000775 }
776
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000777 // Returns true if the object is an Array.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000778 bool isArray() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000779 SkPdfMarkObjectUsed();
780
edisonn@google.com571c70b2013-07-10 17:09:50 +0000781 return fObjectType == kArray_PdfObjectType;
782 }
783
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000784 // Returns true if the object is a Date.
785 // TODO(edisonn): NYI
edisonn@google.com571c70b2013-07-10 17:09:50 +0000786 bool isDate() 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.com2af2ad92013-10-11 16:17:44 +0000792 // Returns true if the object is a Dictionary.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000793 bool isDictionary() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000794 SkPdfMarkObjectUsed();
795
edisonn@google.com571c70b2013-07-10 17:09:50 +0000796 return fObjectType == kDictionary_PdfObjectType;
797 }
798
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000799 // Returns true if the object is a Date.
800 // TODO(edisonn): NYI
edisonn@google.com571c70b2013-07-10 17:09:50 +0000801 bool isFunction() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000802 SkPdfMarkObjectUsed();
803
edisonn@google.com571c70b2013-07-10 17:09:50 +0000804 return false; // NYI
805 }
806
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000807 // Returns true if the object is a Rectangle.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000808 bool isRectangle() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000809 SkPdfMarkObjectUsed();
810
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000811 // TODO(edisonn): add also that each of these 4 objects are numbers.
812 return fObjectType == kArray_PdfObjectType && fArray->count() == 4;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000813 }
814
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000815 // TODO(edisonn): Design: decide if we should use hasStream or isStream
816 // Returns true if the object has a stream associated with it.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000817 bool hasStream() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000818 SkPdfMarkObjectUsed();
819
edisonn@google.com571c70b2013-07-10 17:09:50 +0000820 return isDictionary() && fStr.fBuffer != NULL;
821 }
822
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000823 // Returns the stream associated with the dictionary. As of now, it casts this to Stream.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000824 const SkPdfStream* getStream() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000825 SkPdfMarkObjectUsed();
826
edisonn@google.com571c70b2013-07-10 17:09:50 +0000827 return hasStream() ? (const SkPdfStream*)this : NULL;
828 }
829
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000830 // Returns the stream associated with the dictionary. As of now, it casts this to Stream.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000831 SkPdfStream* getStream() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000832 SkPdfMarkObjectUsed();
833
edisonn@google.com571c70b2013-07-10 17:09:50 +0000834 return hasStream() ? (SkPdfStream*)this : NULL;
835 }
836
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000837 // Returns true if the object is a String or HexString.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000838 bool isAnyString() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000839 SkPdfMarkObjectUsed();
840
edisonn@google.com571c70b2013-07-10 17:09:50 +0000841 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
842 }
843
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000844 // Returns true if the object is a HexString.
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000845 bool isHexString() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000846 SkPdfMarkObjectUsed();
847
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000848 return fObjectType == kHexString_PdfObjectType;
849 }
850
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000851 // Returns true if the object is a Matrix.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000852 bool isMatrix() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000853 SkPdfMarkObjectUsed();
854
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000855 // TODO(edisonn): add also that each of these 6 objects are numbers.
856 return fObjectType == kArray_PdfObjectType && fArray->count() == 6;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000857 }
858
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000859 // Returns the int value stored in the object. Assert if the object is not an Integer.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000860 inline int64_t intValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000861 SkPdfMarkObjectUsed();
862
edisonn@google.com571c70b2013-07-10 17:09:50 +0000863 SkASSERT(fObjectType == kInteger_PdfObjectType);
864
865 if (fObjectType != kInteger_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000866 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000867 return 0;
868 }
869 return fIntegerValue;
870 }
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000871
edisonn@google.com571c70b2013-07-10 17:09:50 +0000872private:
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000873 // Returns the real value stored in the object. Assert if the object is not a Real.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000874 inline double realValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000875 SkPdfMarkObjectUsed();
876
edisonn@google.com571c70b2013-07-10 17:09:50 +0000877 SkASSERT(fObjectType == kReal_PdfObjectType);
878
879 if (fObjectType != kReal_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000880 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000881 return 0;
882 }
883 return fRealValue;
884 }
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000885
edisonn@google.com571c70b2013-07-10 17:09:50 +0000886public:
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000887 // Returns the numeric value stored in the object. Assert if the object is not a Real
888 // or an Integer.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000889 inline double numberValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000890 SkPdfMarkObjectUsed();
891
edisonn@google.com571c70b2013-07-10 17:09:50 +0000892 SkASSERT(isNumber());
893
894 if (!isNumber()) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000895 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000896 return 0;
897 }
898 return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue;
899 }
900
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000901 // Returns the numeric value stored in the object as a scalar. Assert if the object is not
902 // a Realor an Integer.
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000903 inline SkScalar scalarValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000904 SkPdfMarkObjectUsed();
905
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000906 SkASSERT(isNumber());
907
908 if (!isNumber()) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000909 // TODO(edisonn): report/warn/assert.
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000910 return SkIntToScalar(0);
911 }
912 return fObjectType == kReal_PdfObjectType ? SkDoubleToScalar(fRealValue) :
913 SkIntToScalar(fIntegerValue);
914 }
915
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000916 // Returns the id of the referenced object. Assert if the object is not a Reference.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000917 int referenceId() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000918 SkPdfMarkObjectUsed();
919
edisonn@google.com571c70b2013-07-10 17:09:50 +0000920 SkASSERT(fObjectType == kReference_PdfObjectType);
921 return fRef.fId;
922 }
923
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000924 // Returns the generation of the referenced object. Assert if the object is not a Reference.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000925 int referenceGeneration() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000926 SkPdfMarkObjectUsed();
927
edisonn@google.com571c70b2013-07-10 17:09:50 +0000928 SkASSERT(fObjectType == kReference_PdfObjectType);
929 return fRef.fGen;
930 }
931
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000932 // Returns the buffer of a Name object. Assert if the object is not a Name.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000933 inline const char* nameValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000934 SkPdfMarkObjectUsed();
935
edisonn@google.com571c70b2013-07-10 17:09:50 +0000936 SkASSERT(fObjectType == kName_PdfObjectType);
937
938 if (fObjectType != kName_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000939 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000940 return "";
941 }
942 return (const char*)fStr.fBuffer;
943 }
944
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000945 // Returns the buffer of a (Hex)String object. Assert if the object is not a (Hex)String.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000946 inline const char* stringValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000947 SkPdfMarkObjectUsed();
948
edisonn@google.com571c70b2013-07-10 17:09:50 +0000949 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
950
951 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000952 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000953 return "";
954 }
955 return (const char*)fStr.fBuffer;
956 }
957
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000958 // Returns the storage of any type that can hold a form of string.
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000959 inline NotOwnedString strRef() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000960 SkPdfMarkObjectUsed();
961
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000962 switch (fObjectType) {
963 case kString_PdfObjectType:
964 case kHexString_PdfObjectType:
965 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000966 case kName_PdfObjectType:
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000967 return fStr;
968
969 default:
970 // TODO(edisonn): report/warning
971 return NotOwnedString();
972 }
973 }
974
edisonn@google.com571c70b2013-07-10 17:09:50 +0000975 // TODO(edisonn): nameValue2 and stringValue2 are used to make code generation easy,
976 // but it is not a performat way to do it, since it will create an extra copy
977 // remove these functions and make code generated faster
edisonn@google.com063d7072013-08-16 15:05:08 +0000978 inline SkString nameValue2() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000979 SkPdfMarkObjectUsed();
980
edisonn@google.com571c70b2013-07-10 17:09:50 +0000981 SkASSERT(fObjectType == kName_PdfObjectType);
982
983 if (fObjectType != kName_PdfObjectType) {
984 // TODO(edisonn): log err
edisonn@google.com063d7072013-08-16 15:05:08 +0000985 return SkString();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000986 }
edisonn@google.com063d7072013-08-16 15:05:08 +0000987 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000988 }
989
edisonn@google.com2af2ad92013-10-11 16:17:44 +0000990 // Returns an SkString with the value of the (Hex)String object.
edisonn@google.com063d7072013-08-16 15:05:08 +0000991 inline SkString stringValue2() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000992 SkPdfMarkObjectUsed();
993
edisonn@google.com571c70b2013-07-10 17:09:50 +0000994 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
995
996 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +0000997 // TODO(edisonn): report/warn/assert.
edisonn@google.com063d7072013-08-16 15:05:08 +0000998 return SkString();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000999 }
edisonn@google.com063d7072013-08-16 15:05:08 +00001000 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001001 }
1002
edisonn@google.com2af2ad92013-10-11 16:17:44 +00001003 // Returns the boolean of the Bool object. Assert if the object is not a Bool.
edisonn@google.com571c70b2013-07-10 17:09:50 +00001004 inline bool boolValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001005 SkPdfMarkObjectUsed();
1006
edisonn@google.com571c70b2013-07-10 17:09:50 +00001007 SkASSERT(fObjectType == kBoolean_PdfObjectType);
1008
edisonn@google.comf111a4b2013-07-31 18:22:36 +00001009 if (fObjectType != kBoolean_PdfObjectType) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001010 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +00001011 return false;
1012 }
1013 return fBooleanValue;
1014 }
1015
edisonn@google.com2af2ad92013-10-11 16:17:44 +00001016 // Returns the rectangle of the Rectangle object. Assert if the object is not a Rectangle.
edisonn@google.com571c70b2013-07-10 17:09:50 +00001017 SkRect rectangleValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001018 SkPdfMarkObjectUsed();
1019
edisonn@google.com571c70b2013-07-10 17:09:50 +00001020 SkASSERT(isRectangle());
1021 if (!isRectangle()) {
1022 return SkRect::MakeEmpty();
1023 }
1024
1025 double array[4];
1026 for (int i = 0; i < 4; i++) {
1027 // TODO(edisonn): version where we could resolve references?
edisonn@google.com3aa35552013-08-14 18:26:20 +00001028 const SkPdfNativeObject* elem = objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001029 if (elem == NULL || !elem->isNumber()) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001030 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +00001031 return SkRect::MakeEmpty();
1032 }
1033 array[i] = elem->numberValue();
1034 }
1035
1036 return SkRect::MakeLTRB(SkDoubleToScalar(array[0]),
1037 SkDoubleToScalar(array[1]),
1038 SkDoubleToScalar(array[2]),
1039 SkDoubleToScalar(array[3]));
1040 }
1041
edisonn@google.com2af2ad92013-10-11 16:17:44 +00001042 // Returns the matrix of the Matrix object. Assert if the object is not a Matrix.
edisonn@google.com571c70b2013-07-10 17:09:50 +00001043 SkMatrix matrixValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001044 SkPdfMarkObjectUsed();
1045
edisonn@google.com571c70b2013-07-10 17:09:50 +00001046 SkASSERT(isMatrix());
1047 if (!isMatrix()) {
1048 return SkMatrix::I();
1049 }
1050
1051 double array[6];
1052 for (int i = 0; i < 6; i++) {
1053 // TODO(edisonn): version where we could resolve references?
edisonn@google.com3aa35552013-08-14 18:26:20 +00001054 const SkPdfNativeObject* elem = objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001055 if (elem == NULL || !elem->isNumber()) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001056 // TODO(edisonn): report/warn/assert.
edisonn@google.com571c70b2013-07-10 17:09:50 +00001057 return SkMatrix::I();
1058 }
1059 array[i] = elem->numberValue();
1060 }
1061
1062 return SkMatrixFromPdfMatrix(array);
1063 }
1064
edisonn@google.com2af2ad92013-10-11 16:17:44 +00001065 // Runs all the filters of this stream, except the last one, if it is a DCT.
1066 // Returns false on failure.
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001067 bool filterStream();
edisonn@google.com571c70b2013-07-10 17:09:50 +00001068
edisonn@google.com2af2ad92013-10-11 16:17:44 +00001069 // Runs all the filters of this stream, except the last one, if it is a DCT, a gives back
1070 // the buffer and the length. The object continues to own the buffer.
1071 // Returns false on failure.
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001072 bool GetFilteredStreamRef(unsigned char const** buffer, size_t* len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001073 SkPdfMarkObjectUsed();
1074
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001075 // TODO(edisonn): add params that could let the last filter in place
1076 // if it is jpeg or png to fast load images.
edisonn@google.com571c70b2013-07-10 17:09:50 +00001077 if (!hasStream()) {
1078 return false;
1079 }
1080
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001081 filterStream();
edisonn@google.com571c70b2013-07-10 17:09:50 +00001082
1083 if (buffer) {
1084 *buffer = fStr.fBuffer;
1085 }
1086
1087 if (len) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001088 *len = fStr.fBytes >> 2; // last 2 bits - TODO(edisonn): clean up.
edisonn@google.com571c70b2013-07-10 17:09:50 +00001089 }
1090
1091 return true;
1092 }
1093
edisonn@google.com2af2ad92013-10-11 16:17:44 +00001094 // Returns true if the stream is already filtered.
edisonn@google.com571c70b2013-07-10 17:09:50 +00001095 bool isStreamFiltered() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001096 SkPdfMarkObjectUsed();
1097
edisonn@google.com571c70b2013-07-10 17:09:50 +00001098 return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit);
1099 }
1100
edisonn@google.com2af2ad92013-10-11 16:17:44 +00001101 // Returns true if this object own the buffer, or false if an Allocator own it.
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001102 bool isStreamOwned() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001103 SkPdfMarkObjectUsed();
1104
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001105 return hasStream() && ((fStr.fBytes & 2) == kOwnedStreamBit);
1106 }
1107
edisonn@google.com2af2ad92013-10-11 16:17:44 +00001108 // Gives back the original buffer and the length. The object continues to own the buffer.
1109 // Returns false if the stream is already filtered.
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001110 bool GetUnfilteredStreamRef(unsigned char const** buffer, size_t* len) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001111 SkPdfMarkObjectUsed();
1112
edisonn@google.com571c70b2013-07-10 17:09:50 +00001113 if (isStreamFiltered()) {
1114 return false;
1115 }
1116
1117 if (!hasStream()) {
1118 return false;
1119 }
1120
1121 if (buffer) {
1122 *buffer = fStr.fBuffer;
1123 }
1124
1125 if (len) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001126 *len = fStr.fBytes >> 2; // remove last 2 bits - TODO(edisonn): clean up.
edisonn@google.com571c70b2013-07-10 17:09:50 +00001127 }
1128
1129 return true;
1130 }
1131
edisonn@google.com2af2ad92013-10-11 16:17:44 +00001132 // Add a stream to this Dictionarry. Asserts we do not have yet a stream.
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001133 bool addStream(const unsigned char* buffer, size_t len) {
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001134 SkPdfMarkObjectUsed();
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001135
edisonn@google.com571c70b2013-07-10 17:09:50 +00001136 SkASSERT(!hasStream());
1137 SkASSERT(isDictionary());
1138
1139 if (!isDictionary() || hasStream()) {
1140 return false;
1141 }
1142
1143 fStr.fBuffer = buffer;
1144 fStr.fBytes = (len << 2) + kUnfilteredStreamBit;
1145
1146 return true;
1147 }
1148
edisonn@google.com276fed92013-08-01 21:20:47 +00001149 static void appendSpaces(SkString* str, int level) {
edisonn@google.com9a43c182013-08-01 20:06:42 +00001150 for (int i = 0 ; i < level; i++) {
1151 str->append(" ");
1152 }
1153 }
1154
edisonn@google.com3aa35552013-08-14 18:26:20 +00001155 static void append(SkString* str, const char* data, size_t len, const char* prefix = "\\x") {
1156 for (unsigned int i = 0 ; i < len; i++) {
1157 if (data[i] == kNUL_PdfWhiteSpace) {
1158 str->append(prefix);
1159 str->append("00");
1160 } else if (data[i] == kHT_PdfWhiteSpace) {
1161 str->append(prefix);
1162 str->append("09");
1163 } else if (data[i] == kLF_PdfWhiteSpace) {
1164 str->append(prefix);
1165 str->append("0A");
1166 } else if (data[i] == kFF_PdfWhiteSpace) {
1167 str->append(prefix);
1168 str->append("0C");
1169 } else if (data[i] == kCR_PdfWhiteSpace) {
1170 str->append(prefix);
1171 str->append("0D");
1172 } else {
1173 str->append(data + i, 1);
1174 }
1175 }
1176 }
1177
edisonn@google.com2af2ad92013-10-11 16:17:44 +00001178 // Returns the string representation of the object value.
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001179 SkString toString(int firstRowLevel = 0, int level = 0) {
edisonn@google.com571c70b2013-07-10 17:09:50 +00001180 SkString str;
edisonn@google.com9a43c182013-08-01 20:06:42 +00001181 appendSpaces(&str, firstRowLevel);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001182 switch (fObjectType) {
1183 case kInvalid_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001184 str.append("__Invalid");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001185 break;
1186
1187 case kBoolean_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001188 str.appendf("%s", fBooleanValue ? "true" : "false");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001189 break;
1190
1191 case kInteger_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001192 str.appendf("%i", (int)fIntegerValue);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001193 break;
1194
1195 case kReal_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001196 str.appendf("%f", fRealValue);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001197 break;
1198
1199 case kString_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001200 str.append("\"");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001201 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com9a43c182013-08-01 20:06:42 +00001202 str.append("\"");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001203 break;
1204
1205 case kHexString_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001206 str.append("<");
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001207 for (unsigned int i = 0 ; i < fStr.fBytes; i++) {
1208 str.appendf("%02x", (unsigned int)fStr.fBuffer[i]);
1209 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001210 str.append(">");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001211 break;
1212
1213 case kName_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001214 str.append("/");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001215 append(&str, (const char*)fStr.fBuffer, fStr.fBytes, "#");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001216 break;
1217
1218 case kKeyword_PdfObjectType:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001219 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001220 break;
1221
1222 case kArray_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001223 str.append("[\n");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001224 for (unsigned int i = 0; i < size(); i++) {
edisonn@google.com9a43c182013-08-01 20:06:42 +00001225 str.append(objAtAIndex(i)->toString(level + 1, level + 1));
1226 if (i < size() - 1) {
1227 str.append(",");
1228 }
1229 str.append("\n");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001230 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001231 appendSpaces(&str, level);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001232 str.append("]");
1233 break;
1234
edisonn@google.com9a43c182013-08-01 20:06:42 +00001235 case kDictionary_PdfObjectType: {
edisonn@google.com3aa35552013-08-14 18:26:20 +00001236 SkTDict<SkPdfNativeObject*>::Iter iter(*fMap);
1237 SkPdfNativeObject* obj = NULL;
edisonn@google.com9a43c182013-08-01 20:06:42 +00001238 const char* key = NULL;
1239 str.append("<<\n");
1240 while ((key = iter.next(&obj)) != NULL) {
1241 appendSpaces(&str, level + 2);
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001242 str.appendf("/%s %s\n", key,
1243 obj->toString(0, level + strlen(key) + 4).c_str());
edisonn@google.com9a43c182013-08-01 20:06:42 +00001244 }
1245 appendSpaces(&str, level);
1246 str.append(">>");
1247 if (hasStream()) {
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001248 const unsigned char* stream = NULL;
1249 size_t length = 0;
1250 if (GetFilteredStreamRef(&stream, &length)) {
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001251 str.append("stream\n");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001252 append(&str, (const char*)stream, length > 256 ? 256 : length);
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001253 str.append("\nendstream");
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001254 } else {
1255 str.append("stream STREAM_ERROR endstream");
1256 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001257 }
edisonn@google.com571c70b2013-07-10 17:09:50 +00001258 }
1259 break;
1260
1261 case kNull_PdfObjectType:
1262 str = "NULL";
1263 break;
1264
1265 case kReference_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001266 str.appendf("%i %i R", fRef.fId, fRef.fGen);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001267 break;
1268
1269 case kUndefined_PdfObjectType:
1270 str = "Undefined";
1271 break;
1272
1273 default:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001274 str = "Error";
edisonn@google.com571c70b2013-07-10 17:09:50 +00001275 break;
1276 }
1277
1278 return str;
1279 }
1280
1281private:
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001282 static void makeStringCore(const unsigned char* start, SkPdfNativeObject* obj,
1283 ObjectType type) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001284 makeStringCore(start, strlen((const char*)start), obj, type);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001285 }
1286
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001287 static void makeStringCore(const unsigned char* start, const unsigned char* end,
1288 SkPdfNativeObject* obj, ObjectType type) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001289 makeStringCore(start, end - start, obj, type);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001290 }
1291
edisonn@google.comc8fda9d2013-10-09 20:23:12 +00001292 static void makeStringCore(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj,
1293 ObjectType type) {
edisonn@google.com571c70b2013-07-10 17:09:50 +00001294 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
1295
1296 obj->fObjectType = type;
1297 obj->fStr.fBuffer = start;
1298 obj->fStr.fBytes = bytes;
1299 }
1300
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001301 bool applyFilter(const char* name);
1302 bool applyFlateDecodeFilter();
1303 bool applyDCTDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +00001304};
1305
edisonn@google.com2af2ad92013-10-11 16:17:44 +00001306// These classes are provided for convenience. You still have to make sure an SkPdfInteger
1307// is indeed an Integer.
edisonn@google.com3aa35552013-08-14 18:26:20 +00001308class SkPdfStream : public SkPdfNativeObject {};
1309class SkPdfArray : public SkPdfNativeObject {};
1310class SkPdfString : public SkPdfNativeObject {};
1311class SkPdfHexString : public SkPdfNativeObject {};
1312class SkPdfInteger : public SkPdfNativeObject {};
1313class SkPdfReal : public SkPdfNativeObject {};
1314class SkPdfNumber : public SkPdfNativeObject {};
edisonn@google.com571c70b2013-07-10 17:09:50 +00001315
edisonn@google.com3aa35552013-08-14 18:26:20 +00001316class SkPdfName : public SkPdfNativeObject {
1317 SkPdfName() : SkPdfNativeObject() {
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001318 SkPdfNativeObject::makeName((const unsigned char*)"", this);
edisonn@google.com78b38b12013-07-15 18:20:58 +00001319 }
1320public:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001321 SkPdfName(char* name) : SkPdfNativeObject() {
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001322 this->makeName((const unsigned char*)name, this);
edisonn@google.com78b38b12013-07-15 18:20:58 +00001323 }
1324};
1325
edisonn@google.comcf2cfa12013-08-21 16:31:37 +00001326#endif // SkPdfNativeObject