blob: 8c6bf28176cb3c49f2010c1a8359b439297ff40e [file] [log] [blame]
edisonn@google.comcf2cfa12013-08-21 16:31:37 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkPdfNativeObject_DEFINED
9#define SkPdfNativeObject_DEFINED
edisonn@google.com571c70b2013-07-10 17:09:50 +000010
11#include <stdint.h>
12#include <string.h>
edisonn@google.com063d7072013-08-16 15:05:08 +000013#include "SkString.h"
edisonn@google.com571c70b2013-07-10 17:09:50 +000014#include "SkTDArray.h"
15#include "SkTDict.h"
16#include "SkRect.h"
17#include "SkMatrix.h"
18#include "SkString.h"
19
20#include "SkPdfNYI.h"
21#include "SkPdfConfig.h"
edisonn@google.com3aa35552013-08-14 18:26:20 +000022#include "SkPdfUtils.h"
23
24#include "SkPdfNativeTokenizer.h"
edisonn@google.com571c70b2013-07-10 17:09:50 +000025
26class SkPdfDictionary;
27class SkPdfStream;
28class SkPdfAllocator;
29
30// TODO(edisonn): macro it and move it to utils
31SkMatrix SkMatrixFromPdfMatrix(double array[6]);
32
33
34#define kFilteredStreamBit 0
35#define kUnfilteredStreamBit 1
edisonn@google.com2ccc3af2013-07-23 17:43:18 +000036#define kOwnedStreamBit 2
edisonn@google.com571c70b2013-07-10 17:09:50 +000037
edisonn@google.com3aa35552013-08-14 18:26:20 +000038class SkPdfNativeObject {
edisonn@google.com571c70b2013-07-10 17:09:50 +000039 public:
40 enum ObjectType {
edisonn@google.comaf54a512013-09-13 19:33:42 +000041 // The type will have only one of these values, but for error reporting, we make it an enum
42 // so it can easily report that something was expected to be one of a few types
43 kInvalid_PdfObjectType = 1 << 1,
edisonn@google.com571c70b2013-07-10 17:09:50 +000044
edisonn@google.comaf54a512013-09-13 19:33:42 +000045 kBoolean_PdfObjectType = 1 << 2,
46 kInteger_PdfObjectType = 1 << 3,
47 kReal_PdfObjectType = 1 << 4,
48 _kNumber_PdfObjectType = kInteger_PdfObjectType | kReal_PdfObjectType,
49 kString_PdfObjectType = 1 << 5,
50 kHexString_PdfObjectType = 1 << 6,
51 _kAnyString_PdfObjectType = kString_PdfObjectType | kHexString_PdfObjectType,
52 kName_PdfObjectType = 1 << 7,
53 kKeyword_PdfObjectType = 1 << 8,
54 _kStream_PdfObjectType = 1 << 9, // attached to a Dictionary, do not use
55 kArray_PdfObjectType = 1 << 10,
56 kDictionary_PdfObjectType = 1 << 11,
57 kNull_PdfObjectType = 1 << 12,
edisonn@google.com571c70b2013-07-10 17:09:50 +000058
59 // TODO(edisonn): after the pdf has been loaded completely, resolve all references
60 // try the same thing with delayed loaded ...
edisonn@google.comaf54a512013-09-13 19:33:42 +000061 kReference_PdfObjectType = 1 << 13,
edisonn@google.com571c70b2013-07-10 17:09:50 +000062
edisonn@google.comaf54a512013-09-13 19:33:42 +000063 kUndefined_PdfObjectType = 1 << 14, // per 1.4 spec, if the same key appear twice in the dictionary, the value is undefined
64
65 _kObject_PdfObjectType = -1,
edisonn@google.com571c70b2013-07-10 17:09:50 +000066 };
67
edisonn@google.comb0145ce2013-08-05 16:23:23 +000068 enum DataType {
69 kEmpty_Data,
70 kFont_Data,
71 kBitmap_Data,
72 };
73
edisonn@google.com571c70b2013-07-10 17:09:50 +000074private:
edisonn@google.com063d7072013-08-16 15:05:08 +000075 // TODO(edisonn): assert reset operations while in rendering!
76 uint32_t fInRendering : 1;
77 uint32_t fUnused : 31;
78
79
edisonn@google.com571c70b2013-07-10 17:09:50 +000080 struct Reference {
81 unsigned int fId;
82 unsigned int fGen;
83 };
84
85 // TODO(edisonn): add stream start, stream end, where stream is weither the file
86 // or decoded/filtered pdf stream
87
88 // TODO(edisonn): add warning/report per object
89 // TODO(edisonn): add flag fUsed, to be used once the parsing is complete,
90 // so we could show what parts have been proccessed, ignored, or generated errors
91
92 ObjectType fObjectType;
93
94 union {
95 bool fBooleanValue;
96 int64_t fIntegerValue;
97 // TODO(edisonn): double, float? typedefed
98 double fRealValue;
99 NotOwnedString fStr;
100
101 // TODO(edisonn): make sure the foorprint of fArray and fMap is small, otherwise, use pointers, or classes with up to 8 bytes in footprint
edisonn@google.com3aa35552013-08-14 18:26:20 +0000102 SkTDArray<SkPdfNativeObject*>* fArray;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000103 Reference fRef;
104 };
edisonn@google.com3aa35552013-08-14 18:26:20 +0000105 SkTDict<SkPdfNativeObject*>* fMap;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000106
107 // TODO(edisonn): rename data with cache
edisonn@google.com571c70b2013-07-10 17:09:50 +0000108 void* fData;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000109 DataType fDataType;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000110
111
edisonn@google.combca421b2013-09-05 20:00:21 +0000112 // Keep this the last entries
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000113#ifdef PDF_TRACK_OBJECT_USAGE
114 mutable bool fUsed;
115#endif // PDF_TRACK_OBJECT_USAGE
116
edisonn@google.combca421b2013-09-05 20:00:21 +0000117#ifdef PDF_TRACK_STREAM_OFFSETS
edisonn@google.com571c70b2013-07-10 17:09:50 +0000118public:
edisonn@google.combca421b2013-09-05 20:00:21 +0000119 int fStreamId;
120 int fOffsetStart;
121 int fOffsetEnd;
122#endif // PDF_TRACK_STREAM_OFFSETS
123
124public:
125
126#ifdef PDF_TRACK_STREAM_OFFSETS
127 int streamId() const { return fStreamId; }
128 int offsetStart() const { return fOffsetStart; }
129 int offsetEnd() const { return fOffsetEnd; }
130#endif // PDF_TRACK_STREAM_OFFSETS
131
edisonn@google.com571c70b2013-07-10 17:09:50 +0000132
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000133 SkPdfNativeObject() : fInRendering(0)
134 , fObjectType(kInvalid_PdfObjectType)
135 , fMap(NULL)
136 , fData(NULL)
137 , fDataType(kEmpty_Data)
138#ifdef PDF_TRACK_OBJECT_USAGE
139 , fUsed(false)
140#endif // PDF_TRACK_OBJECT_USAGE
edisonn@google.combca421b2013-09-05 20:00:21 +0000141
142#ifdef PDF_TRACK_STREAM_OFFSETS
143 , fStreamId(-1)
144 , fOffsetStart(-1)
145 , fOffsetEnd(-1)
146#endif // PDF_TRACK_STREAM_OFFSETS
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000147 {}
edisonn@google.com571c70b2013-07-10 17:09:50 +0000148
edisonn@google.com063d7072013-08-16 15:05:08 +0000149 bool inRendering() const { return fInRendering != 0; }
150 void startRendering() {fInRendering = 1;}
151 void doneRendering() {fInRendering = 0;}
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000152
153 inline bool hasData(DataType type) {
154 return type == fDataType;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000155 }
156
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000157 inline void* data(DataType type) {
158 return type == fDataType ? fData : NULL;
159 }
160
161 inline void setData(void* data, DataType type) {
162 releaseData();
163 fDataType = type;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000164 fData = data;
165 }
166
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000167 void releaseData();
168
edisonn@google.com3aa35552013-08-14 18:26:20 +0000169// ~SkPdfNativeObject() {
edisonn@google.com222382b2013-07-10 22:33:10 +0000170// //reset(); must be called manually!
171// }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000172
173 void reset() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000174 SkPdfMarkObjectUnused();
175
edisonn@google.com571c70b2013-07-10 17:09:50 +0000176 switch (fObjectType) {
177 case kArray_PdfObjectType:
178 delete fArray;
179 break;
180
181 case kDictionary_PdfObjectType:
182 delete fMap;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000183 if (isStreamOwned()) {
184 delete[] fStr.fBuffer;
185 fStr.fBuffer = NULL;
186 fStr.fBytes = 0;
187 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000188 break;
189
190 default:
191 break;
192 }
193 fObjectType = kInvalid_PdfObjectType;
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000194 releaseData();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000195 }
196
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000197 ObjectType type() {
198 SkPdfMarkObjectUsed();
199
200 return fObjectType;
201 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000202
203 const char* c_str() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000204 SkPdfMarkObjectUsed();
205
edisonn@google.com571c70b2013-07-10 17:09:50 +0000206 switch (fObjectType) {
207 case kString_PdfObjectType:
208 case kHexString_PdfObjectType:
209 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000210 case kName_PdfObjectType:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000211 return (const char*)fStr.fBuffer;
212
213 default:
214 // TODO(edisonn): report/warning
215 return NULL;
216 }
217 }
218
edisonn@google.come878e722013-07-29 19:10:58 +0000219 size_t lenstr() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000220 SkPdfMarkObjectUsed();
221
edisonn@google.com571c70b2013-07-10 17:09:50 +0000222 switch (fObjectType) {
223 case kString_PdfObjectType:
224 case kHexString_PdfObjectType:
225 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000226 case kName_PdfObjectType:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000227 return fStr.fBytes;
228
229 default:
230 // TODO(edisonn): report/warning
231 return 0;
232 }
233 }
234
235
236 // TODO(edisonn): NYI
237 SkPdfDate& dateValue() const {
238 static SkPdfDate nyi;
239 return nyi;
240 }
241
242 // TODO(edisonn): NYI
243 SkPdfFunction& functionValue() const {
244 static SkPdfFunction nyi;
245 return nyi;
246 }
247
248 // TODO(edisonn): NYI
249 SkPdfFileSpec& fileSpecValue() const {
250 static SkPdfFileSpec nyi;
251 return nyi;
252 }
253
254 // TODO(edisonn): NYI
255 SkPdfTree& treeValue() const {
256 static SkPdfTree nyi;
257 return nyi;
258 }
259
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000260 // TODO(edisonn) impl store
261 //STORE_TRACK_PARAMETERS(obj);
262
263 static void makeBoolean(bool value, SkPdfNativeObject* obj) {
edisonn@google.combca421b2013-09-05 20:00:21 +0000264
edisonn@google.com571c70b2013-07-10 17:09:50 +0000265 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
266
267 obj->fObjectType = kBoolean_PdfObjectType;
268 obj->fBooleanValue = value;
269 }
270
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000271 static SkPdfNativeObject makeBoolean(bool value) {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000272 SkPdfNativeObject obj;
edisonn@google.combca421b2013-09-05 20:00:21 +0000273
edisonn@google.com571c70b2013-07-10 17:09:50 +0000274 obj.fObjectType = kBoolean_PdfObjectType;
275 obj.fBooleanValue = value;
276 return obj;
277 }
278
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000279 static void makeInteger(int64_t value, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000280 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
281
282 obj->fObjectType = kInteger_PdfObjectType;
283 obj->fIntegerValue = value;
284 }
285
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000286 static void makeReal(double value, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000287 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
288
289 obj->fObjectType = kReal_PdfObjectType;
290 obj->fRealValue = value;
291 }
292
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000293 static void makeNull(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000294 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
295
296 obj->fObjectType = kNull_PdfObjectType;
297 }
298
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000299 static SkPdfNativeObject makeNull() {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000300 SkPdfNativeObject obj;
edisonn@google.combca421b2013-09-05 20:00:21 +0000301
edisonn@google.com571c70b2013-07-10 17:09:50 +0000302 obj.fObjectType = kNull_PdfObjectType;
303 return obj;
304 }
305
edisonn@google.com3aa35552013-08-14 18:26:20 +0000306 static SkPdfNativeObject kNull;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000307
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000308 static void makeNumeric(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000309 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
310
311 // TODO(edisonn): NYI properly
312 // if has dot (impl), or exceeds max int, is real, otherwise is int
313 bool isInt = true;
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000314 for (const unsigned char* current = start; current < end; current++) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000315 if (*current == '.') {
316 isInt = false;
317 break;
318 }
319 // TODO(edisonn): report parse issue with numbers like "24asdasd123"
320 }
321 if (isInt) {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000322 makeInteger(atol((const char*)start), obj);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000323 } else {
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000324 makeReal(atof((const char*)start), obj);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000325 }
326 }
327
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000328 static void makeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000329 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
330
331 obj->fObjectType = kReference_PdfObjectType;
332 obj->fRef.fId = id;
333 obj->fRef.fGen = gen;
334 }
335
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000336 static void resetAndMakeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj) {
edisonn@google.combca421b2013-09-05 20:00:21 +0000337 obj->reset();
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000338 makeReference(id, gen, obj);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000339 }
340
341
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000342 static void makeString(const unsigned char* start, SkPdfNativeObject* obj) {
343 makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000344 }
345
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000346 static void makeString(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
347 makeStringCore(start, end - start, obj, kString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000348 }
349
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000350 static void makeString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
351 makeStringCore(start, bytes, obj, kString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000352 }
353
354
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000355 static void makeHexString(const unsigned char* start, SkPdfNativeObject* obj) {
356 makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000357 }
358
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000359 static void makeHexString(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
360 makeStringCore(start, end - start, obj, kHexString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000361 }
362
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000363 static void makeHexString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
364 makeStringCore(start, bytes, obj, kHexString_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000365 }
366
367
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000368 static void makeName(const unsigned char* start, SkPdfNativeObject* obj) {
369 makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000370 }
371
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000372 static void makeName(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
373 makeStringCore(start, end - start, obj, kName_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000374 }
375
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000376 static void makeName(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
377 makeStringCore(start, bytes, obj, kName_PdfObjectType);
edisonn@google.combca421b2013-09-05 20:00:21 +0000378 }
379
380
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000381 static void makeKeyword(const unsigned char* start, SkPdfNativeObject* obj) {
382 makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType);
edisonn@google.combca421b2013-09-05 20:00:21 +0000383 }
384
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000385 static void makeKeyword(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj) {
386 makeStringCore(start, end - start, obj, kKeyword_PdfObjectType);
edisonn@google.combca421b2013-09-05 20:00:21 +0000387 }
388
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000389 static void makeKeyword(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) {
390 makeStringCore(start, bytes, obj, kKeyword_PdfObjectType);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000391 }
392
393
394
395 // TODO(edisonn): make the functions to return SkPdfArray, move these functions in SkPdfArray
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000396 static void makeEmptyArray(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000397 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
398
399 obj->fObjectType = kArray_PdfObjectType;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000400 obj->fArray = new SkTDArray<SkPdfNativeObject*>();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000401 // return (SkPdfArray*)obj;
402 }
403
edisonn@google.com3aa35552013-08-14 18:26:20 +0000404 bool appendInArray(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000405 SkASSERT(fObjectType == kArray_PdfObjectType);
406 if (fObjectType != kArray_PdfObjectType) {
407 // TODO(edisonn): report err
408 return false;
409 }
410
411 fArray->push(obj);
412 return true;
413 }
414
415 size_t size() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000416 SkPdfMarkObjectUsed();
417
edisonn@google.com571c70b2013-07-10 17:09:50 +0000418 SkASSERT(fObjectType == kArray_PdfObjectType);
419
420 return fArray->count();
421 }
422
edisonn@google.com3aa35552013-08-14 18:26:20 +0000423 SkPdfNativeObject* objAtAIndex(int i) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000424 SkPdfMarkObjectUsed();
425
edisonn@google.com571c70b2013-07-10 17:09:50 +0000426 SkASSERT(fObjectType == kArray_PdfObjectType);
427
428 return (*fArray)[i];
429 }
430
edisonn@google.com3aa35552013-08-14 18:26:20 +0000431 SkPdfNativeObject* removeLastInArray() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000432 // SkPdfMarkObjectUsed();
433
edisonn@google.com571c70b2013-07-10 17:09:50 +0000434 SkASSERT(fObjectType == kArray_PdfObjectType);
435
edisonn@google.com3aa35552013-08-14 18:26:20 +0000436 SkPdfNativeObject* ret = NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000437 fArray->pop(&ret);
438
439 return ret;
440 }
441
442
edisonn@google.com3aa35552013-08-14 18:26:20 +0000443 const SkPdfNativeObject* objAtAIndex(int i) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000444 SkPdfMarkObjectUsed();
445
edisonn@google.com571c70b2013-07-10 17:09:50 +0000446 SkASSERT(fObjectType == kArray_PdfObjectType);
447
448 return (*fArray)[i];
449 }
450
edisonn@google.com3aa35552013-08-14 18:26:20 +0000451 SkPdfNativeObject* operator[](int i) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000452 SkASSERT(fObjectType == kArray_PdfObjectType);
453
454 return (*fArray)[i];
455 }
456
edisonn@google.com3aa35552013-08-14 18:26:20 +0000457 const SkPdfNativeObject* operator[](int i) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000458 SkPdfMarkObjectUsed();
459
edisonn@google.com571c70b2013-07-10 17:09:50 +0000460 SkASSERT(fObjectType == kArray_PdfObjectType);
461
462 return (*fArray)[i];
463 }
464
465
466 // TODO(edisonn): make the functions to return SkPdfDictionary, move these functions in SkPdfDictionary
edisonn@google.com598cf5d2013-10-09 15:13:19 +0000467 static void makeEmptyDictionary(SkPdfNativeObject* obj) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000468 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
469
470 obj->fObjectType = kDictionary_PdfObjectType;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000471 obj->fMap = new SkTDict<SkPdfNativeObject*>(1);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000472 obj->fStr.fBuffer = NULL;
473 obj->fStr.fBytes = 0;
474 }
475
476 // TODO(edisonn): get all the possible names from spec, and compute a hash function
477 // that would create no overlaps in the same dictionary
478 // or build a tree of chars that when followed goes to a unique id/index/hash
479 // TODO(edisonn): generate constants like kDictFoo, kNameDict_name
480 // which will be used in code
481 // add function SkPdfFastNameKey key(const char* key);
482 // TODO(edisonn): setting the same key twike, will make the value undefined!
edisonn@google.com3aa35552013-08-14 18:26:20 +0000483 bool set(const SkPdfNativeObject* key, SkPdfNativeObject* value) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000484 //SkPdfMarkObjectUsed();
485
edisonn@google.com571c70b2013-07-10 17:09:50 +0000486 SkASSERT(fObjectType == kDictionary_PdfObjectType);
487 SkASSERT(key->fObjectType == kName_PdfObjectType);
488
489 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
490 // TODO(edisonn): report err
491 return false;
492 }
493
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000494 //// we rewrite all delimiters and white spaces with '\0', so we expect the end of name to be '\0'
495 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
edisonn@google.com571c70b2013-07-10 17:09:50 +0000496
edisonn@google.comd761e322013-07-22 17:29:43 +0000497 return set(key->fStr.fBuffer, key->fStr.fBytes, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000498 }
499
edisonn@google.com3aa35552013-08-14 18:26:20 +0000500 bool set(const char* key, SkPdfNativeObject* value) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000501 //SkPdfMarkObjectUsed();
502
edisonn@google.comd761e322013-07-22 17:29:43 +0000503 return set((const unsigned char*)key, strlen(key), value);
504 }
505
edisonn@google.com3aa35552013-08-14 18:26:20 +0000506 bool set(const unsigned char* key, size_t len, SkPdfNativeObject* value) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000507 //SkPdfMarkObjectUsed();
508
edisonn@google.com571c70b2013-07-10 17:09:50 +0000509 SkASSERT(fObjectType == kDictionary_PdfObjectType);
510
511 if (fObjectType != kDictionary_PdfObjectType) {
512 // TODO(edisonn): report err
513 return false;
514 }
515
edisonn@google.comd761e322013-07-22 17:29:43 +0000516 return fMap->set((const char*)key, len, value);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000517 }
518
edisonn@google.com3aa35552013-08-14 18:26:20 +0000519 SkPdfNativeObject* get(const SkPdfNativeObject* key) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000520 SkPdfMarkObjectUsed();
521
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) {
526 // TODO(edisonn): report err
edisonn@google.com3fc48262013-07-22 15:29:55 +0000527 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000528 }
529
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000530 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
edisonn@google.com571c70b2013-07-10 17:09:50 +0000531
edisonn@google.comd761e322013-07-22 17:29:43 +0000532 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000533 }
534
edisonn@google.com3aa35552013-08-14 18:26:20 +0000535 SkPdfNativeObject* get(const char* key) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000536 SkPdfMarkObjectUsed();
537
edisonn@google.comd761e322013-07-22 17:29:43 +0000538 return get((const unsigned char*)key, strlen(key));
539 }
540
edisonn@google.com3aa35552013-08-14 18:26:20 +0000541 SkPdfNativeObject* get(const unsigned char* key, size_t len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000542 SkPdfMarkObjectUsed();
543
edisonn@google.com571c70b2013-07-10 17:09:50 +0000544 SkASSERT(fObjectType == kDictionary_PdfObjectType);
545 SkASSERT(key);
546 if (fObjectType != kDictionary_PdfObjectType) {
547 // TODO(edisonn): report err
548 return NULL;
549 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000550 SkPdfNativeObject* ret = NULL;
edisonn@google.comd761e322013-07-22 17:29:43 +0000551 fMap->find((const char*)key, len, &ret);
edisonn@google.com9a43c182013-08-01 20:06:42 +0000552
553#ifdef PDF_TRACE
554 SkString _key;
555 _key.append((const char*)key, len);
556 printf("\nget(/%s) = %s\n", _key.c_str(), ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
557#endif
558
edisonn@google.com571c70b2013-07-10 17:09:50 +0000559 return ret;
560 }
561
edisonn@google.com3aa35552013-08-14 18:26:20 +0000562 const SkPdfNativeObject* get(const SkPdfNativeObject* key) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000563 SkPdfMarkObjectUsed();
564
edisonn@google.com571c70b2013-07-10 17:09:50 +0000565 SkASSERT(fObjectType == kDictionary_PdfObjectType);
566 SkASSERT(key->fObjectType == kName_PdfObjectType);
567
568 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
569 // TODO(edisonn): report err
edisonn@google.com3fc48262013-07-22 15:29:55 +0000570 return NULL;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000571 }
572
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000573 //SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
edisonn@google.com571c70b2013-07-10 17:09:50 +0000574
edisonn@google.comd761e322013-07-22 17:29:43 +0000575 return get(key->fStr.fBuffer, key->fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000576 }
577
edisonn@google.com3aa35552013-08-14 18:26:20 +0000578 const SkPdfNativeObject* get(const char* key) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000579 SkPdfMarkObjectUsed();
580
edisonn@google.comd761e322013-07-22 17:29:43 +0000581 return get((const unsigned char*)key, strlen(key));
582 }
583
edisonn@google.com3aa35552013-08-14 18:26:20 +0000584 const SkPdfNativeObject* get(const unsigned char* key, size_t len) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000585 SkPdfMarkObjectUsed();
586
edisonn@google.com571c70b2013-07-10 17:09:50 +0000587 SkASSERT(fObjectType == kDictionary_PdfObjectType);
588 SkASSERT(key);
589 if (fObjectType != kDictionary_PdfObjectType) {
590 // TODO(edisonn): report err
591 return NULL;
592 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000593 SkPdfNativeObject* ret = NULL;
edisonn@google.comd761e322013-07-22 17:29:43 +0000594 fMap->find((const char*)key, len, &ret);
edisonn@google.com9a43c182013-08-01 20:06:42 +0000595
596#ifdef PDF_TRACE
597 SkString _key;
598 _key.append((const char*)key, len);
599 printf("\nget(/%s) = %s\n", _key.c_str(), ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND");
600#endif
601
edisonn@google.com571c70b2013-07-10 17:09:50 +0000602 return ret;
603 }
604
edisonn@google.com3aa35552013-08-14 18:26:20 +0000605 const SkPdfNativeObject* get(const char* key, const char* abr) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000606 SkPdfMarkObjectUsed();
607
edisonn@google.com3aa35552013-08-14 18:26:20 +0000608 const SkPdfNativeObject* ret = get(key);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000609 // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL
610 // make this distiontion in generator, and remove "" from condition
611 if (ret != NULL || abr == NULL || *abr == '\0') {
612 return ret;
613 }
614 return get(abr);
615 }
616
edisonn@google.com3aa35552013-08-14 18:26:20 +0000617 SkPdfNativeObject* get(const char* key, const char* abr) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000618 SkPdfMarkObjectUsed();
619
edisonn@google.com3aa35552013-08-14 18:26:20 +0000620 SkPdfNativeObject* ret = get(key);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000621 // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL
622 // make this distiontion in generator, and remove "" from condition
623 if (ret != NULL || abr == NULL || *abr == '\0') {
624 return ret;
625 }
626 return get(abr);
627 }
628
629 SkPdfDictionary* asDictionary() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000630 SkPdfMarkObjectUsed();
631
edisonn@google.com571c70b2013-07-10 17:09:50 +0000632 SkASSERT(isDictionary());
633 if (!isDictionary()) {
634 return NULL;
635 }
636 return (SkPdfDictionary*) this;
637 }
638
639 const SkPdfDictionary* asDictionary() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000640 SkPdfMarkObjectUsed();
641
edisonn@google.com571c70b2013-07-10 17:09:50 +0000642 SkASSERT(isDictionary());
643 if (!isDictionary()) {
644 return NULL;
645 }
646 return (SkPdfDictionary*) this;
647 }
648
649
650 bool isReference() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000651 SkPdfMarkObjectUsed();
652
edisonn@google.com571c70b2013-07-10 17:09:50 +0000653 return fObjectType == kReference_PdfObjectType;
654 }
655
656 bool isBoolean() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000657 SkPdfMarkObjectUsed();
658
edisonn@google.com571c70b2013-07-10 17:09:50 +0000659 return fObjectType == kBoolean_PdfObjectType;
660 }
661
662 bool isInteger() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000663 SkPdfMarkObjectUsed();
664
edisonn@google.com571c70b2013-07-10 17:09:50 +0000665 return fObjectType == kInteger_PdfObjectType;
666 }
667private:
668 bool isReal() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000669 SkPdfMarkObjectUsed();
670
edisonn@google.com571c70b2013-07-10 17:09:50 +0000671 return fObjectType == kReal_PdfObjectType;
672 }
673public:
674 bool isNumber() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000675 SkPdfMarkObjectUsed();
676
edisonn@google.com571c70b2013-07-10 17:09:50 +0000677 return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_PdfObjectType;
678 }
679
680 bool isKeywordReference() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000681 SkPdfMarkObjectUsed();
682
edisonn@google.com571c70b2013-07-10 17:09:50 +0000683 return fObjectType == kKeyword_PdfObjectType && fStr.fBytes == 1 && fStr.fBuffer[0] == 'R';
684 }
685
686 bool isKeyword() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000687 SkPdfMarkObjectUsed();
688
edisonn@google.com571c70b2013-07-10 17:09:50 +0000689 return fObjectType == kKeyword_PdfObjectType;
690 }
691
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000692 bool isKeyword(const char* keyword) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000693 SkPdfMarkObjectUsed();
694
edisonn@google.com4ef4bed2013-07-29 22:14:45 +0000695 if (!isKeyword()) {
696 return false;
697 }
698
699 if (strlen(keyword) != fStr.fBytes) {
700 return false;
701 }
702
703 if (strncmp(keyword, (const char*)fStr.fBuffer, fStr.fBytes) != 0) {
704 return false;
705 }
706
707 return true;
708 }
709
edisonn@google.com571c70b2013-07-10 17:09:50 +0000710 bool isName() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000711 SkPdfMarkObjectUsed();
712
edisonn@google.com571c70b2013-07-10 17:09:50 +0000713 return fObjectType == kName_PdfObjectType;
714 }
715
edisonn@google.com78b38b12013-07-15 18:20:58 +0000716 bool isName(const char* name) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000717 SkPdfMarkObjectUsed();
718
edisonn@google.com78b38b12013-07-15 18:20:58 +0000719 return fObjectType == kName_PdfObjectType && fStr.fBytes == strlen(name) && strncmp((const char*)fStr.fBuffer, name, fStr.fBytes) == 0;
720 }
721
edisonn@google.com571c70b2013-07-10 17:09:50 +0000722 bool isArray() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000723 SkPdfMarkObjectUsed();
724
edisonn@google.com571c70b2013-07-10 17:09:50 +0000725 return fObjectType == kArray_PdfObjectType;
726 }
727
728 bool isDate() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000729 SkPdfMarkObjectUsed();
730
edisonn@google.com571c70b2013-07-10 17:09:50 +0000731 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
732 }
733
734 bool isDictionary() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000735 SkPdfMarkObjectUsed();
736
edisonn@google.com571c70b2013-07-10 17:09:50 +0000737 return fObjectType == kDictionary_PdfObjectType;
738 }
739
740 bool isFunction() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000741 SkPdfMarkObjectUsed();
742
edisonn@google.com571c70b2013-07-10 17:09:50 +0000743 return false; // NYI
744 }
745
746 bool isRectangle() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000747 SkPdfMarkObjectUsed();
748
edisonn@google.com571c70b2013-07-10 17:09:50 +0000749 return fObjectType == kArray_PdfObjectType && fArray->count() == 4; // NYI + and elems are numbers
750 }
751
752 // TODO(edisonn): has stream .. or is stream ... TBD
753 bool hasStream() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000754 SkPdfMarkObjectUsed();
755
edisonn@google.com571c70b2013-07-10 17:09:50 +0000756 return isDictionary() && fStr.fBuffer != NULL;
757 }
758
759 // TODO(edisonn): has stream .. or is stream ... TBD
760 const SkPdfStream* getStream() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000761 SkPdfMarkObjectUsed();
762
edisonn@google.com571c70b2013-07-10 17:09:50 +0000763 return hasStream() ? (const SkPdfStream*)this : NULL;
764 }
765
766 SkPdfStream* getStream() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000767 SkPdfMarkObjectUsed();
768
edisonn@google.com571c70b2013-07-10 17:09:50 +0000769 return hasStream() ? (SkPdfStream*)this : NULL;
770 }
771
772 bool isAnyString() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000773 SkPdfMarkObjectUsed();
774
edisonn@google.com571c70b2013-07-10 17:09:50 +0000775 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
776 }
777
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000778 bool isHexString() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000779 SkPdfMarkObjectUsed();
780
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000781 return fObjectType == kHexString_PdfObjectType;
782 }
783
edisonn@google.com571c70b2013-07-10 17:09:50 +0000784 bool isMatrix() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000785 SkPdfMarkObjectUsed();
786
edisonn@google.com571c70b2013-07-10 17:09:50 +0000787 return fObjectType == kArray_PdfObjectType && fArray->count() == 6; // NYI + and elems are numbers
788 }
789
790 inline int64_t intValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000791 SkPdfMarkObjectUsed();
792
edisonn@google.com571c70b2013-07-10 17:09:50 +0000793 SkASSERT(fObjectType == kInteger_PdfObjectType);
794
795 if (fObjectType != kInteger_PdfObjectType) {
796 // TODO(edisonn): log err
797 return 0;
798 }
799 return fIntegerValue;
800 }
801private:
802 inline double realValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000803 SkPdfMarkObjectUsed();
804
edisonn@google.com571c70b2013-07-10 17:09:50 +0000805 SkASSERT(fObjectType == kReal_PdfObjectType);
806
807 if (fObjectType != kReal_PdfObjectType) {
808 // TODO(edisonn): log err
809 return 0;
810 }
811 return fRealValue;
812 }
813public:
814 inline double numberValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000815 SkPdfMarkObjectUsed();
816
edisonn@google.com571c70b2013-07-10 17:09:50 +0000817 SkASSERT(isNumber());
818
819 if (!isNumber()) {
820 // TODO(edisonn): log err
821 return 0;
822 }
823 return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue;
824 }
825
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000826 inline SkScalar scalarValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000827 SkPdfMarkObjectUsed();
828
edisonn@google.coma0cefa12013-07-28 18:34:14 +0000829 SkASSERT(isNumber());
830
831 if (!isNumber()) {
832 // TODO(edisonn): log err
833 return SkIntToScalar(0);
834 }
835 return fObjectType == kReal_PdfObjectType ? SkDoubleToScalar(fRealValue) :
836 SkIntToScalar(fIntegerValue);
837 }
838
edisonn@google.com571c70b2013-07-10 17:09:50 +0000839 int referenceId() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000840 SkPdfMarkObjectUsed();
841
edisonn@google.com571c70b2013-07-10 17:09:50 +0000842 SkASSERT(fObjectType == kReference_PdfObjectType);
843 return fRef.fId;
844 }
845
846 int referenceGeneration() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000847 SkPdfMarkObjectUsed();
848
edisonn@google.com571c70b2013-07-10 17:09:50 +0000849 SkASSERT(fObjectType == kReference_PdfObjectType);
850 return fRef.fGen;
851 }
852
853 inline const char* nameValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000854 SkPdfMarkObjectUsed();
855
edisonn@google.com571c70b2013-07-10 17:09:50 +0000856 SkASSERT(fObjectType == kName_PdfObjectType);
857
858 if (fObjectType != kName_PdfObjectType) {
859 // TODO(edisonn): log err
860 return "";
861 }
862 return (const char*)fStr.fBuffer;
863 }
864
865 inline const char* stringValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000866 SkPdfMarkObjectUsed();
867
edisonn@google.com571c70b2013-07-10 17:09:50 +0000868 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
869
870 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
871 // TODO(edisonn): log err
872 return "";
873 }
874 return (const char*)fStr.fBuffer;
875 }
876
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000877 inline NotOwnedString strRef() {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000878 SkPdfMarkObjectUsed();
879
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000880 switch (fObjectType) {
881 case kString_PdfObjectType:
882 case kHexString_PdfObjectType:
883 case kKeyword_PdfObjectType:
edisonn@google.com276fed92013-08-01 21:20:47 +0000884 case kName_PdfObjectType:
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000885 return fStr;
886
887 default:
888 // TODO(edisonn): report/warning
889 return NotOwnedString();
890 }
891 }
892
edisonn@google.com571c70b2013-07-10 17:09:50 +0000893 // TODO(edisonn): nameValue2 and stringValue2 are used to make code generation easy,
894 // but it is not a performat way to do it, since it will create an extra copy
895 // remove these functions and make code generated faster
edisonn@google.com063d7072013-08-16 15:05:08 +0000896 inline SkString nameValue2() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000897 SkPdfMarkObjectUsed();
898
edisonn@google.com571c70b2013-07-10 17:09:50 +0000899 SkASSERT(fObjectType == kName_PdfObjectType);
900
901 if (fObjectType != kName_PdfObjectType) {
902 // TODO(edisonn): log err
edisonn@google.com063d7072013-08-16 15:05:08 +0000903 return SkString();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000904 }
edisonn@google.com063d7072013-08-16 15:05:08 +0000905 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000906 }
907
edisonn@google.com063d7072013-08-16 15:05:08 +0000908 inline SkString stringValue2() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000909 SkPdfMarkObjectUsed();
910
edisonn@google.com571c70b2013-07-10 17:09:50 +0000911 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
912
913 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
914 // TODO(edisonn): log err
edisonn@google.com063d7072013-08-16 15:05:08 +0000915 return SkString();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000916 }
edisonn@google.com063d7072013-08-16 15:05:08 +0000917 return SkString((const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000918 }
919
920 inline bool boolValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000921 SkPdfMarkObjectUsed();
922
edisonn@google.com571c70b2013-07-10 17:09:50 +0000923 SkASSERT(fObjectType == kBoolean_PdfObjectType);
924
edisonn@google.comf111a4b2013-07-31 18:22:36 +0000925 if (fObjectType != kBoolean_PdfObjectType) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000926 // TODO(edisonn): log err
927 return false;
928 }
929 return fBooleanValue;
930 }
931
932 SkRect rectangleValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000933 SkPdfMarkObjectUsed();
934
edisonn@google.com571c70b2013-07-10 17:09:50 +0000935 SkASSERT(isRectangle());
936 if (!isRectangle()) {
937 return SkRect::MakeEmpty();
938 }
939
940 double array[4];
941 for (int i = 0; i < 4; i++) {
942 // TODO(edisonn): version where we could resolve references?
edisonn@google.com3aa35552013-08-14 18:26:20 +0000943 const SkPdfNativeObject* elem = objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000944 if (elem == NULL || !elem->isNumber()) {
945 // TODO(edisonn): report error
946 return SkRect::MakeEmpty();
947 }
948 array[i] = elem->numberValue();
949 }
950
951 return SkRect::MakeLTRB(SkDoubleToScalar(array[0]),
952 SkDoubleToScalar(array[1]),
953 SkDoubleToScalar(array[2]),
954 SkDoubleToScalar(array[3]));
955 }
956
957 SkMatrix matrixValue() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000958 SkPdfMarkObjectUsed();
959
edisonn@google.com571c70b2013-07-10 17:09:50 +0000960 SkASSERT(isMatrix());
961 if (!isMatrix()) {
962 return SkMatrix::I();
963 }
964
965 double array[6];
966 for (int i = 0; i < 6; i++) {
967 // TODO(edisonn): version where we could resolve references?
edisonn@google.com3aa35552013-08-14 18:26:20 +0000968 const SkPdfNativeObject* elem = objAtAIndex(i);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000969 if (elem == NULL || !elem->isNumber()) {
970 // TODO(edisonn): report error
971 return SkMatrix::I();
972 }
973 array[i] = elem->numberValue();
974 }
975
976 return SkMatrixFromPdfMatrix(array);
977 }
978
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000979 bool filterStream();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000980
981
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000982 bool GetFilteredStreamRef(unsigned char const** buffer, size_t* len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +0000983 SkPdfMarkObjectUsed();
984
edisonn@google.com571c70b2013-07-10 17:09:50 +0000985 // TODO(edisonn): add params that couls let the last filter in place if it is jpeg or png to fast load images
986 if (!hasStream()) {
987 return false;
988 }
989
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000990 filterStream();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000991
992 if (buffer) {
993 *buffer = fStr.fBuffer;
994 }
995
996 if (len) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000997 *len = fStr.fBytes >> 2; // last 2 bits
edisonn@google.com571c70b2013-07-10 17:09:50 +0000998 }
999
1000 return true;
1001 }
1002
1003 bool isStreamFiltered() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001004 SkPdfMarkObjectUsed();
1005
edisonn@google.com571c70b2013-07-10 17:09:50 +00001006 return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit);
1007 }
1008
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001009 bool isStreamOwned() const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001010 SkPdfMarkObjectUsed();
1011
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001012 return hasStream() && ((fStr.fBytes & 2) == kOwnedStreamBit);
1013 }
1014
1015 bool GetUnfilteredStreamRef(unsigned char const** buffer, size_t* len) const {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001016 SkPdfMarkObjectUsed();
1017
edisonn@google.com571c70b2013-07-10 17:09:50 +00001018 if (isStreamFiltered()) {
1019 return false;
1020 }
1021
1022 if (!hasStream()) {
1023 return false;
1024 }
1025
1026 if (buffer) {
1027 *buffer = fStr.fBuffer;
1028 }
1029
1030 if (len) {
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001031 *len = fStr.fBytes >> 2; // remove last 2 bits
edisonn@google.com571c70b2013-07-10 17:09:50 +00001032 }
1033
1034 return true;
1035 }
1036
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001037 bool addStream(const unsigned char* buffer, size_t len) {
edisonn@google.com0fd25d82013-09-05 16:40:34 +00001038 //SkPdfMarkObjectUsed();
1039
edisonn@google.com571c70b2013-07-10 17:09:50 +00001040 SkASSERT(!hasStream());
1041 SkASSERT(isDictionary());
1042
1043 if (!isDictionary() || hasStream()) {
1044 return false;
1045 }
1046
1047 fStr.fBuffer = buffer;
1048 fStr.fBytes = (len << 2) + kUnfilteredStreamBit;
1049
1050 return true;
1051 }
1052
edisonn@google.com276fed92013-08-01 21:20:47 +00001053 static void appendSpaces(SkString* str, int level) {
edisonn@google.com9a43c182013-08-01 20:06:42 +00001054 for (int i = 0 ; i < level; i++) {
1055 str->append(" ");
1056 }
1057 }
1058
edisonn@google.com3aa35552013-08-14 18:26:20 +00001059 static void append(SkString* str, const char* data, size_t len, const char* prefix = "\\x") {
1060 for (unsigned int i = 0 ; i < len; i++) {
1061 if (data[i] == kNUL_PdfWhiteSpace) {
1062 str->append(prefix);
1063 str->append("00");
1064 } else if (data[i] == kHT_PdfWhiteSpace) {
1065 str->append(prefix);
1066 str->append("09");
1067 } else if (data[i] == kLF_PdfWhiteSpace) {
1068 str->append(prefix);
1069 str->append("0A");
1070 } else if (data[i] == kFF_PdfWhiteSpace) {
1071 str->append(prefix);
1072 str->append("0C");
1073 } else if (data[i] == kCR_PdfWhiteSpace) {
1074 str->append(prefix);
1075 str->append("0D");
1076 } else {
1077 str->append(data + i, 1);
1078 }
1079 }
1080 }
1081
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001082 SkString toString(int firstRowLevel = 0, int level = 0) {
edisonn@google.com571c70b2013-07-10 17:09:50 +00001083 SkString str;
edisonn@google.com9a43c182013-08-01 20:06:42 +00001084 appendSpaces(&str, firstRowLevel);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001085 switch (fObjectType) {
1086 case kInvalid_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001087 str.append("__Invalid");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001088 break;
1089
1090 case kBoolean_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001091 str.appendf("%s", fBooleanValue ? "true" : "false");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001092 break;
1093
1094 case kInteger_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001095 str.appendf("%i", (int)fIntegerValue);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001096 break;
1097
1098 case kReal_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001099 str.appendf("%f", fRealValue);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001100 break;
1101
1102 case kString_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001103 str.append("\"");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001104 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com9a43c182013-08-01 20:06:42 +00001105 str.append("\"");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001106 break;
1107
1108 case kHexString_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001109 str.append("<");
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001110 for (unsigned int i = 0 ; i < fStr.fBytes; i++) {
1111 str.appendf("%02x", (unsigned int)fStr.fBuffer[i]);
1112 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001113 str.append(">");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001114 break;
1115
1116 case kName_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001117 str.append("/");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001118 append(&str, (const char*)fStr.fBuffer, fStr.fBytes, "#");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001119 break;
1120
1121 case kKeyword_PdfObjectType:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001122 append(&str, (const char*)fStr.fBuffer, fStr.fBytes);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001123 break;
1124
1125 case kArray_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001126 str.append("[\n");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001127 for (unsigned int i = 0; i < size(); i++) {
edisonn@google.com9a43c182013-08-01 20:06:42 +00001128 str.append(objAtAIndex(i)->toString(level + 1, level + 1));
1129 if (i < size() - 1) {
1130 str.append(",");
1131 }
1132 str.append("\n");
edisonn@google.com571c70b2013-07-10 17:09:50 +00001133 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001134 appendSpaces(&str, level);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001135 str.append("]");
1136 break;
1137
edisonn@google.com9a43c182013-08-01 20:06:42 +00001138 case kDictionary_PdfObjectType: {
edisonn@google.com3aa35552013-08-14 18:26:20 +00001139 SkTDict<SkPdfNativeObject*>::Iter iter(*fMap);
1140 SkPdfNativeObject* obj = NULL;
edisonn@google.com9a43c182013-08-01 20:06:42 +00001141 const char* key = NULL;
1142 str.append("<<\n");
1143 while ((key = iter.next(&obj)) != NULL) {
1144 appendSpaces(&str, level + 2);
1145 str.appendf("/%s %s\n", key, obj->toString(0, level + strlen(key) + 4).c_str());
1146 }
1147 appendSpaces(&str, level);
1148 str.append(">>");
1149 if (hasStream()) {
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001150 const unsigned char* stream = NULL;
1151 size_t length = 0;
1152 if (GetFilteredStreamRef(&stream, &length)) {
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001153 str.append("stream\n");
edisonn@google.com3aa35552013-08-14 18:26:20 +00001154 append(&str, (const char*)stream, length > 256 ? 256 : length);
edisonn@google.comb0145ce2013-08-05 16:23:23 +00001155 str.append("\nendstream");
edisonn@google.come2e01ff2013-08-02 20:24:48 +00001156 } else {
1157 str.append("stream STREAM_ERROR endstream");
1158 }
edisonn@google.com9a43c182013-08-01 20:06:42 +00001159 }
edisonn@google.com571c70b2013-07-10 17:09:50 +00001160 }
1161 break;
1162
1163 case kNull_PdfObjectType:
1164 str = "NULL";
1165 break;
1166
1167 case kReference_PdfObjectType:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001168 str.appendf("%i %i R", fRef.fId, fRef.fGen);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001169 break;
1170
1171 case kUndefined_PdfObjectType:
1172 str = "Undefined";
1173 break;
1174
1175 default:
edisonn@google.com9a43c182013-08-01 20:06:42 +00001176 str = "Error";
edisonn@google.com571c70b2013-07-10 17:09:50 +00001177 break;
1178 }
1179
1180 return str;
1181 }
1182
1183private:
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001184 static void makeStringCore(const unsigned char* start, SkPdfNativeObject* obj, ObjectType type) {
1185 makeStringCore(start, strlen((const char*)start), obj, type);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001186 }
1187
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001188 static void makeStringCore(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* obj, ObjectType type) {
1189 makeStringCore(start, end - start, obj, type);
edisonn@google.com571c70b2013-07-10 17:09:50 +00001190 }
1191
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001192 static void makeStringCore(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj, ObjectType type) {
edisonn@google.combca421b2013-09-05 20:00:21 +00001193
edisonn@google.com571c70b2013-07-10 17:09:50 +00001194 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
1195
1196 obj->fObjectType = type;
1197 obj->fStr.fBuffer = start;
1198 obj->fStr.fBytes = bytes;
1199 }
1200
edisonn@google.com2ccc3af2013-07-23 17:43:18 +00001201 bool applyFilter(const char* name);
1202 bool applyFlateDecodeFilter();
1203 bool applyDCTDecodeFilter();
edisonn@google.com571c70b2013-07-10 17:09:50 +00001204};
1205
edisonn@google.com3aa35552013-08-14 18:26:20 +00001206class SkPdfStream : public SkPdfNativeObject {};
1207class SkPdfArray : public SkPdfNativeObject {};
1208class SkPdfString : public SkPdfNativeObject {};
1209class SkPdfHexString : public SkPdfNativeObject {};
1210class SkPdfInteger : public SkPdfNativeObject {};
1211class SkPdfReal : public SkPdfNativeObject {};
1212class SkPdfNumber : public SkPdfNativeObject {};
edisonn@google.com571c70b2013-07-10 17:09:50 +00001213
edisonn@google.com3aa35552013-08-14 18:26:20 +00001214class SkPdfName : public SkPdfNativeObject {
1215 SkPdfName() : SkPdfNativeObject() {
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001216 SkPdfNativeObject::makeName((const unsigned char*)"", this);
edisonn@google.com78b38b12013-07-15 18:20:58 +00001217 }
1218public:
edisonn@google.com3aa35552013-08-14 18:26:20 +00001219 SkPdfName(char* name) : SkPdfNativeObject() {
edisonn@google.com598cf5d2013-10-09 15:13:19 +00001220 this->makeName((const unsigned char*)name, this);
edisonn@google.com78b38b12013-07-15 18:20:58 +00001221 }
1222};
1223
edisonn@google.comcf2cfa12013-08-21 16:31:37 +00001224#endif // SkPdfNativeObject