SkPdfNativeObject.h revision c8fda9d96be0bd944d37a6e23f7adad5f247c51d
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2013 Google Inc. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be 55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * found in the LICENSE file. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifndef SkPdfNativeObject_DEFINED 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SkPdfNativeObject_DEFINED 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkMatrix.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkPdfConfig.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkPdfNativeTokenizer.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkPdfNYI.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkPdfUtils.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkRect.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkString.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkTDArray.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkTDict.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkPdfDictionary; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkPdfStream; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkPdfAllocator; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(edisonn): remove these constants and clean up the code. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define kFilteredStreamBit 0 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define kUnfilteredStreamBit 1 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define kOwnedStreamBit 2 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SkPdfNativeObject { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum ObjectType { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The type will have only one of these values, but for error reporting, we make it an enum 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so it can easily report that something was expected to be one of a few types 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kInvalid_PdfObjectType = 1 << 1, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kBoolean_PdfObjectType = 1 << 2, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kInteger_PdfObjectType = 1 << 3, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kReal_PdfObjectType = 1 << 4, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _kNumber_PdfObjectType = kInteger_PdfObjectType | kReal_PdfObjectType, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kString_PdfObjectType = 1 << 5, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kHexString_PdfObjectType = 1 << 6, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _kAnyString_PdfObjectType = kString_PdfObjectType | kHexString_PdfObjectType, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kName_PdfObjectType = 1 << 7, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kKeyword_PdfObjectType = 1 << 8, 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _kStream_PdfObjectType = 1 << 9, // attached to a Dictionary, do not use 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kArray_PdfObjectType = 1 << 10, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kDictionary_PdfObjectType = 1 << 11, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kNull_PdfObjectType = 1 << 12, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kReference_PdfObjectType = 1 << 13, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kUndefined_PdfObjectType = 1 << 14, // per 1.4 spec, if the same key appear twice in the 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dictionary, the value is undefined. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _kObject_PdfObjectType = -1, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum DataType { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kEmpty_Data, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kFont_Data, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kBitmap_Data, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private: 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(edisonn): assert reset operations while in rendering! The objects should be reset 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only when rendering is completed. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t fInRendering : 1; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t fUnused : 31; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Reference { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int fId; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int fGen; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObjectType fObjectType; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) union { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool fBooleanValue; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64_t fIntegerValue; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(edisonn): double, float, SkScalar? 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double fRealValue; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotOwnedString fStr; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkTDArray<SkPdfNativeObject*>* fArray; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Reference fRef; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkTDict<SkPdfNativeObject*>* fMap; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(edisonn): rename data with cache 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* fData; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DataType fDataType; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keep this the last entries 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PDF_TRACK_OBJECT_USAGE 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable bool fUsed; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // PDF_TRACK_OBJECT_USAGE 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PDF_TRACK_STREAM_OFFSETS 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fStreamId; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fOffsetStart; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fOffsetEnd; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // PDF_TRACK_STREAM_OFFSETS 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PDF_TRACK_STREAM_OFFSETS 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int streamId() const { return fStreamId; } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int offsetStart() const { return fOffsetStart; } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int offsetEnd() const { return fOffsetEnd; } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // PDF_TRACK_STREAM_OFFSETS 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkPdfNativeObject() : fInRendering(0) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) , fObjectType(kInvalid_PdfObjectType) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) , fMap(NULL) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) , fData(NULL) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) , fDataType(kEmpty_Data) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PDF_TRACK_OBJECT_USAGE 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) , fUsed(false) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // PDF_TRACK_OBJECT_USAGE 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PDF_TRACK_STREAM_OFFSETS 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) , fStreamId(-1) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) , fOffsetStart(-1) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) , fOffsetEnd(-1) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // PDF_TRACK_STREAM_OFFSETS 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool inRendering() const { return fInRendering != 0; } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void startRendering() {fInRendering = 1;} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void doneRendering() {fInRendering = 0;} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline bool hasData(DataType type) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type == fDataType; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline void* data(DataType type) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return type == fDataType ? fData : NULL; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inline void setData(void* data, DataType type) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) releaseData(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fDataType = type; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fData = data; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void releaseData(); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ~SkPdfNativeObject() { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// //reset(); must be called manually! Normally, will be called by allocator destructor. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void reset() { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkPdfMarkObjectUnused(); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (fObjectType) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kArray_PdfObjectType: 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete fArray; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kDictionary_PdfObjectType: 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete fMap; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isStreamOwned()) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] fStr.fBuffer; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fStr.fBuffer = NULL; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fStr.fBytes = 0; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fObjectType = kInvalid_PdfObjectType; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) releaseData(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 182 ObjectType type() { 183 SkPdfMarkObjectUsed(); 184 185 return fObjectType; 186 } 187 188 const char* c_str() const { 189 SkPdfMarkObjectUsed(); 190 191 switch (fObjectType) { 192 case kString_PdfObjectType: 193 case kHexString_PdfObjectType: 194 case kKeyword_PdfObjectType: 195 case kName_PdfObjectType: 196 return (const char*)fStr.fBuffer; 197 198 default: 199 // TODO(edisonn): report/warning/assert? 200 return NULL; 201 } 202 } 203 204 size_t lenstr() const { 205 SkPdfMarkObjectUsed(); 206 207 switch (fObjectType) { 208 case kString_PdfObjectType: 209 case kHexString_PdfObjectType: 210 case kKeyword_PdfObjectType: 211 case kName_PdfObjectType: 212 return fStr.fBytes; 213 214 default: 215 // TODO(edisonn): report/warning/assert? 216 return 0; 217 } 218 } 219 220 221 // TODO(edisonn): NYI 222 SkPdfDate& dateValue() const { 223 static SkPdfDate nyi; 224 return nyi; 225 } 226 227 // TODO(edisonn): NYI 228 SkPdfFunction& functionValue() const { 229 static SkPdfFunction nyi; 230 return nyi; 231 } 232 233 // TODO(edisonn): NYI 234 SkPdfFileSpec& fileSpecValue() const { 235 static SkPdfFileSpec nyi; 236 return nyi; 237 } 238 239 // TODO(edisonn): NYI 240 SkPdfTree& treeValue() const { 241 static SkPdfTree nyi; 242 return nyi; 243 } 244 245 static void makeBoolean(bool value, SkPdfNativeObject* obj) { 246 247 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 248 249 obj->fObjectType = kBoolean_PdfObjectType; 250 obj->fBooleanValue = value; 251 } 252 253 static SkPdfNativeObject makeBoolean(bool value) { 254 SkPdfNativeObject obj; 255 256 obj.fObjectType = kBoolean_PdfObjectType; 257 obj.fBooleanValue = value; 258 return obj; 259 } 260 261 static void makeInteger(int64_t value, SkPdfNativeObject* obj) { 262 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 263 264 obj->fObjectType = kInteger_PdfObjectType; 265 obj->fIntegerValue = value; 266 } 267 268 static void makeReal(double value, SkPdfNativeObject* obj) { 269 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 270 271 obj->fObjectType = kReal_PdfObjectType; 272 obj->fRealValue = value; 273 } 274 275 static void makeNull(SkPdfNativeObject* obj) { 276 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 277 278 obj->fObjectType = kNull_PdfObjectType; 279 } 280 281 static SkPdfNativeObject makeNull() { 282 SkPdfNativeObject obj; 283 284 obj.fObjectType = kNull_PdfObjectType; 285 return obj; 286 } 287 288 static SkPdfNativeObject kNull; 289 290 static void makeNumeric(const unsigned char* start, const unsigned char* end, 291 SkPdfNativeObject* obj) { 292 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 293 294 // TODO(edisonn): NYI properly 295 // if has dot (impl), or exceeds max int, is real, otherwise is int 296 bool isInt = true; 297 for (const unsigned char* current = start; current < end; current++) { 298 if (*current == '.') { 299 isInt = false; 300 break; 301 } 302 // TODO(edisonn): report parse issue with numbers like "24asdasd123" 303 } 304 if (isInt) { 305 makeInteger(atol((const char*)start), obj); 306 } else { 307 makeReal(atof((const char*)start), obj); 308 } 309 } 310 311 static void makeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj) { 312 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 313 314 obj->fObjectType = kReference_PdfObjectType; 315 obj->fRef.fId = id; 316 obj->fRef.fGen = gen; 317 } 318 319 static void resetAndMakeReference(unsigned int id, unsigned int gen, SkPdfNativeObject* obj) { 320 obj->reset(); 321 makeReference(id, gen, obj); 322 } 323 324 325 static void makeString(const unsigned char* start, SkPdfNativeObject* obj) { 326 makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType); 327 } 328 329 static void makeString(const unsigned char* start, const unsigned char* end, 330 SkPdfNativeObject* obj) { 331 makeStringCore(start, end - start, obj, kString_PdfObjectType); 332 } 333 334 static void makeString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) { 335 makeStringCore(start, bytes, obj, kString_PdfObjectType); 336 } 337 338 339 static void makeHexString(const unsigned char* start, SkPdfNativeObject* obj) { 340 makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType); 341 } 342 343 static void makeHexString(const unsigned char* start, const unsigned char* end, 344 SkPdfNativeObject* obj) { 345 makeStringCore(start, end - start, obj, kHexString_PdfObjectType); 346 } 347 348 static void makeHexString(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) { 349 makeStringCore(start, bytes, obj, kHexString_PdfObjectType); 350 } 351 352 353 static void makeName(const unsigned char* start, SkPdfNativeObject* obj) { 354 makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType); 355 } 356 357 static void makeName(const unsigned char* start, const unsigned char* end, 358 SkPdfNativeObject* obj) { 359 makeStringCore(start, end - start, obj, kName_PdfObjectType); 360 } 361 362 static void makeName(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) { 363 makeStringCore(start, bytes, obj, kName_PdfObjectType); 364 } 365 366 367 static void makeKeyword(const unsigned char* start, SkPdfNativeObject* obj) { 368 makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType); 369 } 370 371 static void makeKeyword(const unsigned char* start, const unsigned char* end, 372 SkPdfNativeObject* obj) { 373 makeStringCore(start, end - start, obj, kKeyword_PdfObjectType); 374 } 375 376 static void makeKeyword(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj) { 377 makeStringCore(start, bytes, obj, kKeyword_PdfObjectType); 378 } 379 380 static void makeEmptyArray(SkPdfNativeObject* obj) { 381 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 382 383 obj->fObjectType = kArray_PdfObjectType; 384 obj->fArray = new SkTDArray<SkPdfNativeObject*>(); 385 } 386 387 bool appendInArray(SkPdfNativeObject* obj) { 388 SkASSERT(fObjectType == kArray_PdfObjectType); 389 if (fObjectType != kArray_PdfObjectType) { 390 // TODO(edisonn): report/warning/assert? 391 return false; 392 } 393 394 fArray->push(obj); 395 return true; 396 } 397 398 size_t size() const { 399 SkPdfMarkObjectUsed(); 400 401 SkASSERT(fObjectType == kArray_PdfObjectType); 402 403 return fArray->count(); 404 } 405 406 SkPdfNativeObject* objAtAIndex(int i) { 407 SkPdfMarkObjectUsed(); 408 409 SkASSERT(fObjectType == kArray_PdfObjectType); 410 411 return (*fArray)[i]; 412 } 413 414 SkPdfNativeObject* removeLastInArray() { 415 SkPdfMarkObjectUsed(); 416 417 SkASSERT(fObjectType == kArray_PdfObjectType); 418 419 SkPdfNativeObject* ret = NULL; 420 fArray->pop(&ret); 421 422 return ret; 423 } 424 425 const SkPdfNativeObject* objAtAIndex(int i) const { 426 SkPdfMarkObjectUsed(); 427 428 SkASSERT(fObjectType == kArray_PdfObjectType); 429 430 return (*fArray)[i]; 431 } 432 433 SkPdfNativeObject* operator[](int i) { 434 SkPdfMarkObjectUsed(); 435 436 SkASSERT(fObjectType == kArray_PdfObjectType); 437 438 return (*fArray)[i]; 439 } 440 441 const SkPdfNativeObject* operator[](int i) const { 442 SkPdfMarkObjectUsed(); 443 444 SkASSERT(fObjectType == kArray_PdfObjectType); 445 446 return (*fArray)[i]; 447 } 448 449 static void makeEmptyDictionary(SkPdfNativeObject* obj) { 450 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 451 452 obj->fObjectType = kDictionary_PdfObjectType; 453 obj->fMap = new SkTDict<SkPdfNativeObject*>(1); 454 obj->fStr.fBuffer = NULL; 455 obj->fStr.fBytes = 0; 456 } 457 458 // TODO(edisonn): perf: get all the possible names from spec, and compute a hash function 459 // that would create no overlaps in the same dictionary 460 // or build a tree of chars that when followed goes to a unique id/index/hash 461 // TODO(edisonn): generate constants like kDictFoo, kNameDict_name 462 // which will be used in code 463 // add function SkPdfFastNameKey key(const char* key); 464 // TODO(edisonn): setting the same key twice, will make the value undefined! 465 bool set(const SkPdfNativeObject* key, SkPdfNativeObject* value) { 466 SkPdfMarkObjectUsed(); 467 468 SkASSERT(fObjectType == kDictionary_PdfObjectType); 469 SkASSERT(key->fObjectType == kName_PdfObjectType); 470 471 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) { 472 // TODO(edisonn): report/warn/assert? 473 return false; 474 } 475 476 return set(key->fStr.fBuffer, key->fStr.fBytes, value); 477 } 478 479 bool set(const char* key, SkPdfNativeObject* value) { 480 SkPdfMarkObjectUsed(); 481 482 return set((const unsigned char*)key, strlen(key), value); 483 } 484 485 bool set(const unsigned char* key, size_t len, SkPdfNativeObject* value) { 486 SkPdfMarkObjectUsed(); 487 488 SkASSERT(fObjectType == kDictionary_PdfObjectType); 489 490 if (fObjectType != kDictionary_PdfObjectType) { 491 // TODO(edisonn): report/warn/assert. 492 return false; 493 } 494 495 return fMap->set((const char*)key, len, value); 496 } 497 498 SkPdfNativeObject* get(const SkPdfNativeObject* key) { 499 SkPdfMarkObjectUsed(); 500 501 SkASSERT(fObjectType == kDictionary_PdfObjectType); 502 SkASSERT(key->fObjectType == kName_PdfObjectType); 503 504 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) { 505 // TODO(edisonn): report/warn/assert. 506 return NULL; 507 } 508 509 return get(key->fStr.fBuffer, key->fStr.fBytes); 510 } 511 512 SkPdfNativeObject* get(const char* key) { 513 SkPdfMarkObjectUsed(); 514 515 return get((const unsigned char*)key, strlen(key)); 516 } 517 518 SkPdfNativeObject* get(const unsigned char* key, size_t len) { 519 SkPdfMarkObjectUsed(); 520 521 SkASSERT(fObjectType == kDictionary_PdfObjectType); 522 SkASSERT(key); 523 if (fObjectType != kDictionary_PdfObjectType) { 524 // TODO(edisonn): report/warn/assert. 525 return NULL; 526 } 527 SkPdfNativeObject* ret = NULL; 528 fMap->find((const char*)key, len, &ret); 529 530#ifdef PDF_TRACE 531 SkString _key; 532 _key.append((const char*)key, len); 533 printf("\nget(/%s) = %s\n", _key.c_str(), 534 ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND"); 535#endif 536 537 return ret; 538 } 539 540 const SkPdfNativeObject* get(const SkPdfNativeObject* key) const { 541 SkPdfMarkObjectUsed(); 542 543 SkASSERT(fObjectType == kDictionary_PdfObjectType); 544 SkASSERT(key->fObjectType == kName_PdfObjectType); 545 546 if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) { 547 // TODO(edisonn): report/warn/assert. 548 return NULL; 549 } 550 551 return get(key->fStr.fBuffer, key->fStr.fBytes); 552 } 553 554 const SkPdfNativeObject* get(const char* key) const { 555 SkPdfMarkObjectUsed(); 556 557 return get((const unsigned char*)key, strlen(key)); 558 } 559 560 const SkPdfNativeObject* get(const unsigned char* key, size_t len) const { 561 SkPdfMarkObjectUsed(); 562 563 SkASSERT(fObjectType == kDictionary_PdfObjectType); 564 SkASSERT(key); 565 if (fObjectType != kDictionary_PdfObjectType) { 566 // TODO(edisonn): report/warn/assert. 567 return NULL; 568 } 569 SkPdfNativeObject* ret = NULL; 570 fMap->find((const char*)key, len, &ret); 571 572#ifdef PDF_TRACE 573 SkString _key; 574 _key.append((const char*)key, len); 575 printf("\nget(/%s) = %s\n", _key.c_str(), 576 ret ? ret->toString(0, len + 9).c_str() : "_NOT_FOUND"); 577#endif 578 579 return ret; 580 } 581 582 const SkPdfNativeObject* get(const char* key, const char* abr) const { 583 SkPdfMarkObjectUsed(); 584 585 const SkPdfNativeObject* ret = get(key); 586 // TODO(edisonn): remove || *abr == '\0' and pass NULL in the _autogen files instead. 587 if (ret != NULL || abr == NULL || *abr == '\0') { 588 return ret; 589 } 590 return get(abr); 591 } 592 593 SkPdfNativeObject* get(const char* key, const char* abr) { 594 SkPdfMarkObjectUsed(); 595 596 SkPdfNativeObject* ret = get(key); 597 // TODO(edisonn): remove || *abr == '\0' and pass NULL in the _autogen files instead. 598 if (ret != NULL || abr == NULL || *abr == '\0') { 599 return ret; 600 } 601 return get(abr); 602 } 603 604 SkPdfDictionary* asDictionary() { 605 SkPdfMarkObjectUsed(); 606 607 SkASSERT(isDictionary()); 608 if (!isDictionary()) { 609 return NULL; 610 } 611 return (SkPdfDictionary*) this; 612 } 613 614 const SkPdfDictionary* asDictionary() const { 615 SkPdfMarkObjectUsed(); 616 617 SkASSERT(isDictionary()); 618 if (!isDictionary()) { 619 return NULL; 620 } 621 return (SkPdfDictionary*) this; 622 } 623 624 625 bool isReference() const { 626 SkPdfMarkObjectUsed(); 627 628 return fObjectType == kReference_PdfObjectType; 629 } 630 631 bool isBoolean() const { 632 SkPdfMarkObjectUsed(); 633 634 return fObjectType == kBoolean_PdfObjectType; 635 } 636 637 bool isInteger() const { 638 SkPdfMarkObjectUsed(); 639 640 return fObjectType == kInteger_PdfObjectType; 641 } 642private: 643 bool isReal() const { 644 SkPdfMarkObjectUsed(); 645 646 return fObjectType == kReal_PdfObjectType; 647 } 648public: 649 bool isNumber() const { 650 SkPdfMarkObjectUsed(); 651 652 return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_PdfObjectType; 653 } 654 655 bool isKeywordReference() const { 656 SkPdfMarkObjectUsed(); 657 658 return fObjectType == kKeyword_PdfObjectType && fStr.fBytes == 1 && fStr.fBuffer[0] == 'R'; 659 } 660 661 bool isKeyword() const { 662 SkPdfMarkObjectUsed(); 663 664 return fObjectType == kKeyword_PdfObjectType; 665 } 666 667 bool isKeyword(const char* keyword) const { 668 SkPdfMarkObjectUsed(); 669 670 if (!isKeyword()) { 671 return false; 672 } 673 674 if (strlen(keyword) != fStr.fBytes) { 675 return false; 676 } 677 678 if (strncmp(keyword, (const char*)fStr.fBuffer, fStr.fBytes) != 0) { 679 return false; 680 } 681 682 return true; 683 } 684 685 bool isName() const { 686 SkPdfMarkObjectUsed(); 687 688 return fObjectType == kName_PdfObjectType; 689 } 690 691 bool isName(const char* name) const { 692 SkPdfMarkObjectUsed(); 693 694 return fObjectType == kName_PdfObjectType && 695 fStr.fBytes == strlen(name) && 696 strncmp((const char*)fStr.fBuffer, name, fStr.fBytes) == 0; 697 } 698 699 bool isArray() const { 700 SkPdfMarkObjectUsed(); 701 702 return fObjectType == kArray_PdfObjectType; 703 } 704 705 bool isDate() const { 706 SkPdfMarkObjectUsed(); 707 708 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType; 709 } 710 711 bool isDictionary() const { 712 SkPdfMarkObjectUsed(); 713 714 return fObjectType == kDictionary_PdfObjectType; 715 } 716 717 bool isFunction() const { 718 SkPdfMarkObjectUsed(); 719 720 return false; // NYI 721 } 722 723 bool isRectangle() const { 724 SkPdfMarkObjectUsed(); 725 726 // TODO(edisonn): add also that each of these 4 objects are numbers. 727 return fObjectType == kArray_PdfObjectType && fArray->count() == 4; 728 } 729 730 // TODO(edisonn): has stream .. or is stream ... TBD 731 bool hasStream() const { 732 SkPdfMarkObjectUsed(); 733 734 return isDictionary() && fStr.fBuffer != NULL; 735 } 736 737 // TODO(edisonn): has stream .. or is stream ... TBD 738 const SkPdfStream* getStream() const { 739 SkPdfMarkObjectUsed(); 740 741 return hasStream() ? (const SkPdfStream*)this : NULL; 742 } 743 744 SkPdfStream* getStream() { 745 SkPdfMarkObjectUsed(); 746 747 return hasStream() ? (SkPdfStream*)this : NULL; 748 } 749 750 bool isAnyString() const { 751 SkPdfMarkObjectUsed(); 752 753 return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType; 754 } 755 756 bool isHexString() const { 757 SkPdfMarkObjectUsed(); 758 759 return fObjectType == kHexString_PdfObjectType; 760 } 761 762 bool isMatrix() const { 763 SkPdfMarkObjectUsed(); 764 765 // TODO(edisonn): add also that each of these 6 objects are numbers. 766 return fObjectType == kArray_PdfObjectType && fArray->count() == 6; 767 } 768 769 inline int64_t intValue() const { 770 SkPdfMarkObjectUsed(); 771 772 SkASSERT(fObjectType == kInteger_PdfObjectType); 773 774 if (fObjectType != kInteger_PdfObjectType) { 775 // TODO(edisonn): report/warn/assert. 776 return 0; 777 } 778 return fIntegerValue; 779 } 780private: 781 inline double realValue() const { 782 SkPdfMarkObjectUsed(); 783 784 SkASSERT(fObjectType == kReal_PdfObjectType); 785 786 if (fObjectType != kReal_PdfObjectType) { 787 // TODO(edisonn): report/warn/assert. 788 return 0; 789 } 790 return fRealValue; 791 } 792public: 793 inline double numberValue() const { 794 SkPdfMarkObjectUsed(); 795 796 SkASSERT(isNumber()); 797 798 if (!isNumber()) { 799 // TODO(edisonn): report/warn/assert. 800 return 0; 801 } 802 return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue; 803 } 804 805 inline SkScalar scalarValue() const { 806 SkPdfMarkObjectUsed(); 807 808 SkASSERT(isNumber()); 809 810 if (!isNumber()) { 811 // TODO(edisonn): report/warn/assert. 812 return SkIntToScalar(0); 813 } 814 return fObjectType == kReal_PdfObjectType ? SkDoubleToScalar(fRealValue) : 815 SkIntToScalar(fIntegerValue); 816 } 817 818 int referenceId() const { 819 SkPdfMarkObjectUsed(); 820 821 SkASSERT(fObjectType == kReference_PdfObjectType); 822 return fRef.fId; 823 } 824 825 int referenceGeneration() const { 826 SkPdfMarkObjectUsed(); 827 828 SkASSERT(fObjectType == kReference_PdfObjectType); 829 return fRef.fGen; 830 } 831 832 inline const char* nameValue() const { 833 SkPdfMarkObjectUsed(); 834 835 SkASSERT(fObjectType == kName_PdfObjectType); 836 837 if (fObjectType != kName_PdfObjectType) { 838 // TODO(edisonn): report/warn/assert. 839 return ""; 840 } 841 return (const char*)fStr.fBuffer; 842 } 843 844 inline const char* stringValue() const { 845 SkPdfMarkObjectUsed(); 846 847 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType); 848 849 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) { 850 // TODO(edisonn): report/warn/assert. 851 return ""; 852 } 853 return (const char*)fStr.fBuffer; 854 } 855 856 inline NotOwnedString strRef() { 857 SkPdfMarkObjectUsed(); 858 859 switch (fObjectType) { 860 case kString_PdfObjectType: 861 case kHexString_PdfObjectType: 862 case kKeyword_PdfObjectType: 863 case kName_PdfObjectType: 864 return fStr; 865 866 default: 867 // TODO(edisonn): report/warning 868 return NotOwnedString(); 869 } 870 } 871 872 // TODO(edisonn): nameValue2 and stringValue2 are used to make code generation easy, 873 // but it is not a performat way to do it, since it will create an extra copy 874 // remove these functions and make code generated faster 875 inline SkString nameValue2() const { 876 SkPdfMarkObjectUsed(); 877 878 SkASSERT(fObjectType == kName_PdfObjectType); 879 880 if (fObjectType != kName_PdfObjectType) { 881 // TODO(edisonn): log err 882 return SkString(); 883 } 884 return SkString((const char*)fStr.fBuffer, fStr.fBytes); 885 } 886 887 inline SkString stringValue2() const { 888 SkPdfMarkObjectUsed(); 889 890 SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType); 891 892 if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) { 893 // TODO(edisonn): report/warn/assert. 894 return SkString(); 895 } 896 return SkString((const char*)fStr.fBuffer, fStr.fBytes); 897 } 898 899 inline bool boolValue() const { 900 SkPdfMarkObjectUsed(); 901 902 SkASSERT(fObjectType == kBoolean_PdfObjectType); 903 904 if (fObjectType != kBoolean_PdfObjectType) { 905 // TODO(edisonn): report/warn/assert. 906 return false; 907 } 908 return fBooleanValue; 909 } 910 911 SkRect rectangleValue() const { 912 SkPdfMarkObjectUsed(); 913 914 SkASSERT(isRectangle()); 915 if (!isRectangle()) { 916 return SkRect::MakeEmpty(); 917 } 918 919 double array[4]; 920 for (int i = 0; i < 4; i++) { 921 // TODO(edisonn): version where we could resolve references? 922 const SkPdfNativeObject* elem = objAtAIndex(i); 923 if (elem == NULL || !elem->isNumber()) { 924 // TODO(edisonn): report/warn/assert. 925 return SkRect::MakeEmpty(); 926 } 927 array[i] = elem->numberValue(); 928 } 929 930 return SkRect::MakeLTRB(SkDoubleToScalar(array[0]), 931 SkDoubleToScalar(array[1]), 932 SkDoubleToScalar(array[2]), 933 SkDoubleToScalar(array[3])); 934 } 935 936 SkMatrix matrixValue() const { 937 SkPdfMarkObjectUsed(); 938 939 SkASSERT(isMatrix()); 940 if (!isMatrix()) { 941 return SkMatrix::I(); 942 } 943 944 double array[6]; 945 for (int i = 0; i < 6; i++) { 946 // TODO(edisonn): version where we could resolve references? 947 const SkPdfNativeObject* elem = objAtAIndex(i); 948 if (elem == NULL || !elem->isNumber()) { 949 // TODO(edisonn): report/warn/assert. 950 return SkMatrix::I(); 951 } 952 array[i] = elem->numberValue(); 953 } 954 955 return SkMatrixFromPdfMatrix(array); 956 } 957 958 bool filterStream(); 959 960 961 bool GetFilteredStreamRef(unsigned char const** buffer, size_t* len) { 962 SkPdfMarkObjectUsed(); 963 964 // TODO(edisonn): add params that could let the last filter in place 965 // if it is jpeg or png to fast load images. 966 if (!hasStream()) { 967 return false; 968 } 969 970 filterStream(); 971 972 if (buffer) { 973 *buffer = fStr.fBuffer; 974 } 975 976 if (len) { 977 *len = fStr.fBytes >> 2; // last 2 bits - TODO(edisonn): clean up. 978 } 979 980 return true; 981 } 982 983 bool isStreamFiltered() const { 984 SkPdfMarkObjectUsed(); 985 986 return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit); 987 } 988 989 bool isStreamOwned() const { 990 SkPdfMarkObjectUsed(); 991 992 return hasStream() && ((fStr.fBytes & 2) == kOwnedStreamBit); 993 } 994 995 bool GetUnfilteredStreamRef(unsigned char const** buffer, size_t* len) const { 996 SkPdfMarkObjectUsed(); 997 998 if (isStreamFiltered()) { 999 return false; 1000 } 1001 1002 if (!hasStream()) { 1003 return false; 1004 } 1005 1006 if (buffer) { 1007 *buffer = fStr.fBuffer; 1008 } 1009 1010 if (len) { 1011 *len = fStr.fBytes >> 2; // remove last 2 bits - TODO(edisonn): clean up. 1012 } 1013 1014 return true; 1015 } 1016 1017 bool addStream(const unsigned char* buffer, size_t len) { 1018 SkPdfMarkObjectUsed(); 1019 1020 SkASSERT(!hasStream()); 1021 SkASSERT(isDictionary()); 1022 1023 if (!isDictionary() || hasStream()) { 1024 return false; 1025 } 1026 1027 fStr.fBuffer = buffer; 1028 fStr.fBytes = (len << 2) + kUnfilteredStreamBit; 1029 1030 return true; 1031 } 1032 1033 static void appendSpaces(SkString* str, int level) { 1034 for (int i = 0 ; i < level; i++) { 1035 str->append(" "); 1036 } 1037 } 1038 1039 static void append(SkString* str, const char* data, size_t len, const char* prefix = "\\x") { 1040 for (unsigned int i = 0 ; i < len; i++) { 1041 if (data[i] == kNUL_PdfWhiteSpace) { 1042 str->append(prefix); 1043 str->append("00"); 1044 } else if (data[i] == kHT_PdfWhiteSpace) { 1045 str->append(prefix); 1046 str->append("09"); 1047 } else if (data[i] == kLF_PdfWhiteSpace) { 1048 str->append(prefix); 1049 str->append("0A"); 1050 } else if (data[i] == kFF_PdfWhiteSpace) { 1051 str->append(prefix); 1052 str->append("0C"); 1053 } else if (data[i] == kCR_PdfWhiteSpace) { 1054 str->append(prefix); 1055 str->append("0D"); 1056 } else { 1057 str->append(data + i, 1); 1058 } 1059 } 1060 } 1061 1062 SkString toString(int firstRowLevel = 0, int level = 0) { 1063 SkString str; 1064 appendSpaces(&str, firstRowLevel); 1065 switch (fObjectType) { 1066 case kInvalid_PdfObjectType: 1067 str.append("__Invalid"); 1068 break; 1069 1070 case kBoolean_PdfObjectType: 1071 str.appendf("%s", fBooleanValue ? "true" : "false"); 1072 break; 1073 1074 case kInteger_PdfObjectType: 1075 str.appendf("%i", (int)fIntegerValue); 1076 break; 1077 1078 case kReal_PdfObjectType: 1079 str.appendf("%f", fRealValue); 1080 break; 1081 1082 case kString_PdfObjectType: 1083 str.append("\""); 1084 append(&str, (const char*)fStr.fBuffer, fStr.fBytes); 1085 str.append("\""); 1086 break; 1087 1088 case kHexString_PdfObjectType: 1089 str.append("<"); 1090 for (unsigned int i = 0 ; i < fStr.fBytes; i++) { 1091 str.appendf("%02x", (unsigned int)fStr.fBuffer[i]); 1092 } 1093 str.append(">"); 1094 break; 1095 1096 case kName_PdfObjectType: 1097 str.append("/"); 1098 append(&str, (const char*)fStr.fBuffer, fStr.fBytes, "#"); 1099 break; 1100 1101 case kKeyword_PdfObjectType: 1102 append(&str, (const char*)fStr.fBuffer, fStr.fBytes); 1103 break; 1104 1105 case kArray_PdfObjectType: 1106 str.append("[\n"); 1107 for (unsigned int i = 0; i < size(); i++) { 1108 str.append(objAtAIndex(i)->toString(level + 1, level + 1)); 1109 if (i < size() - 1) { 1110 str.append(","); 1111 } 1112 str.append("\n"); 1113 } 1114 appendSpaces(&str, level); 1115 str.append("]"); 1116 break; 1117 1118 case kDictionary_PdfObjectType: { 1119 SkTDict<SkPdfNativeObject*>::Iter iter(*fMap); 1120 SkPdfNativeObject* obj = NULL; 1121 const char* key = NULL; 1122 str.append("<<\n"); 1123 while ((key = iter.next(&obj)) != NULL) { 1124 appendSpaces(&str, level + 2); 1125 str.appendf("/%s %s\n", key, 1126 obj->toString(0, level + strlen(key) + 4).c_str()); 1127 } 1128 appendSpaces(&str, level); 1129 str.append(">>"); 1130 if (hasStream()) { 1131 const unsigned char* stream = NULL; 1132 size_t length = 0; 1133 if (GetFilteredStreamRef(&stream, &length)) { 1134 str.append("stream\n"); 1135 append(&str, (const char*)stream, length > 256 ? 256 : length); 1136 str.append("\nendstream"); 1137 } else { 1138 str.append("stream STREAM_ERROR endstream"); 1139 } 1140 } 1141 } 1142 break; 1143 1144 case kNull_PdfObjectType: 1145 str = "NULL"; 1146 break; 1147 1148 case kReference_PdfObjectType: 1149 str.appendf("%i %i R", fRef.fId, fRef.fGen); 1150 break; 1151 1152 case kUndefined_PdfObjectType: 1153 str = "Undefined"; 1154 break; 1155 1156 default: 1157 str = "Error"; 1158 break; 1159 } 1160 1161 return str; 1162 } 1163 1164private: 1165 static void makeStringCore(const unsigned char* start, SkPdfNativeObject* obj, 1166 ObjectType type) { 1167 makeStringCore(start, strlen((const char*)start), obj, type); 1168 } 1169 1170 static void makeStringCore(const unsigned char* start, const unsigned char* end, 1171 SkPdfNativeObject* obj, ObjectType type) { 1172 makeStringCore(start, end - start, obj, type); 1173 } 1174 1175 static void makeStringCore(const unsigned char* start, size_t bytes, SkPdfNativeObject* obj, 1176 ObjectType type) { 1177 SkASSERT(obj->fObjectType == kInvalid_PdfObjectType); 1178 1179 obj->fObjectType = type; 1180 obj->fStr.fBuffer = start; 1181 obj->fStr.fBytes = bytes; 1182 } 1183 1184 bool applyFilter(const char* name); 1185 bool applyFlateDecodeFilter(); 1186 bool applyDCTDecodeFilter(); 1187}; 1188 1189class SkPdfStream : public SkPdfNativeObject {}; 1190class SkPdfArray : public SkPdfNativeObject {}; 1191class SkPdfString : public SkPdfNativeObject {}; 1192class SkPdfHexString : public SkPdfNativeObject {}; 1193class SkPdfInteger : public SkPdfNativeObject {}; 1194class SkPdfReal : public SkPdfNativeObject {}; 1195class SkPdfNumber : public SkPdfNativeObject {}; 1196 1197class SkPdfName : public SkPdfNativeObject { 1198 SkPdfName() : SkPdfNativeObject() { 1199 SkPdfNativeObject::makeName((const unsigned char*)"", this); 1200 } 1201public: 1202 SkPdfName(char* name) : SkPdfNativeObject() { 1203 this->makeName((const unsigned char*)name, this); 1204 } 1205}; 1206 1207#endif // SkPdfNativeObject 1208