SkPdfNativeObject.h revision d761e3295c10e467d5ae4a5f52ad80c85b656e23
102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFOBJECT_H_
202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFOBJECT_H_
302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#include <stdint.h>
502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#include <string.h>
602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#include <string>
702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#include "SkTDArray.h"
802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#include "SkTDict.h"
902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#include "SkRect.h"
1002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#include "SkMatrix.h"
1102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#include "SkString.h"
1202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
1302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#include "SkPdfNYI.h"
1402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#include "SkPdfConfig.h"
1502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
1602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Projectclass SkPdfDictionary;
1702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Projectclass SkPdfStream;
1802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Projectclass SkPdfAllocator;
1902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
2002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project// TODO(edisonn): macro it and move it to utils
2102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source ProjectSkMatrix SkMatrixFromPdfMatrix(double array[6]);
2202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
2302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
2402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#define kFilteredStreamBit 0
2502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project#define kUnfilteredStreamBit 1
2602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
2702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
2802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Projectclass SkPdfObject {
2902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project public:
3002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project     enum ObjectType {
3102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kInvalid_PdfObjectType,
3202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
3302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kBoolean_PdfObjectType,
3402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kInteger_PdfObjectType,
3502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kReal_PdfObjectType,
3602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kString_PdfObjectType,
3702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kHexString_PdfObjectType,
3802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kName_PdfObjectType,
3902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kKeyword_PdfObjectType,
4002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         //kStream_PdfObjectType,  //  attached to a Dictionary
4102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kArray_PdfObjectType,
4202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kDictionary_PdfObjectType,
4302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kNull_PdfObjectType,
4402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
4502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         // TODO(edisonn): after the pdf has been loaded completely, resolve all references
4602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         // try the same thing with delayed loaded ...
4702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kReference_PdfObjectType,
4802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
4902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project         kUndefined_PdfObjectType,  // per 1.4 spec, if the same key appear twice in the dictionary, the value is undefined
5002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project     };
5102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
5202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Projectprivate:
5302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    struct NotOwnedString {
5402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        unsigned char* fBuffer;
5502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        size_t fBytes;
5602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    };
5702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
5802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    struct Reference {
5902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        unsigned int fId;
6002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        unsigned int fGen;
6102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    };
6202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
6302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    // TODO(edisonn): add stream start, stream end, where stream is weither the file
6402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    // or decoded/filtered pdf stream
6502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
6602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    // TODO(edisonn): add warning/report per object
6702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    // TODO(edisonn): add flag fUsed, to be used once the parsing is complete,
6802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    // so we could show what parts have been proccessed, ignored, or generated errors
6902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
7002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    ObjectType fObjectType;
7102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
7202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    union {
7302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        bool fBooleanValue;
7402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        int64_t fIntegerValue;
7502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        // TODO(edisonn): double, float? typedefed
7602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        double fRealValue;
7702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        NotOwnedString fStr;
7802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
7902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        // TODO(edisonn): make sure the foorprint of fArray and fMap is small, otherwise, use pointers, or classes with up to 8 bytes in footprint
8002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        SkTDArray<SkPdfObject*>* fArray;
8102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        Reference fRef;
8202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    };
8302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    SkTDict<SkPdfObject*>* fMap;
8402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    void* fData;
8502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
8602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
8702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Projectpublic:
8802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
8902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    SkPdfObject() : fObjectType(kInvalid_PdfObjectType), fMap(NULL), fData(NULL) {}
9002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
9102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    inline void* data() {
9202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        return fData;
9302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
9402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
9502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    inline void setData(void* data) {
9602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        fData = data;
9702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
9802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
9902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project//    ~SkPdfObject() {
10002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project//        //reset();  must be called manually!
10102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project//    }
10202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
10302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    void reset() {
10402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        switch (fObjectType) {
10502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            case kArray_PdfObjectType:
10602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                delete fArray;
10702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                break;
10802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
10902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            case kDictionary_PdfObjectType:
11002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                delete fMap;
11102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                break;
11202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
11302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            default:
11402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                break;
11502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        }
11602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        fObjectType = kInvalid_PdfObjectType;
11702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
11802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
11902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    ObjectType type() { return fObjectType; }
12002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
12102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    const char* c_str() const {
12202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        switch (fObjectType) {
12302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            case kString_PdfObjectType:
12402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            case kHexString_PdfObjectType:
12502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            case kKeyword_PdfObjectType:
12602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                return (const char*)fStr.fBuffer;
12702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
12802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            default:
12902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                // TODO(edisonn): report/warning
13002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                return NULL;
13102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        }
13202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
13302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
13402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    size_t len() const {
13502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        switch (fObjectType) {
13602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            case kString_PdfObjectType:
13702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            case kHexString_PdfObjectType:
13802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            case kKeyword_PdfObjectType:
13902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                return fStr.fBytes;
14002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
14102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            default:
14202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                // TODO(edisonn): report/warning
14302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                return 0;
14402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        }
14502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
14602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
14702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
14802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    // TODO(edisonn): NYI
14902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    SkPdfDate& dateValue() const {
15002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        static SkPdfDate nyi;
15102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        return nyi;
15202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
15302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
15402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    // TODO(edisonn): NYI
15502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    SkPdfFunction& functionValue() const {
15602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        static SkPdfFunction nyi;
15702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        return nyi;
15802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
15902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
16002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    // TODO(edisonn): NYI
16102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    SkPdfFileSpec& fileSpecValue() const {
16202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        static SkPdfFileSpec nyi;
16302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        return nyi;
16402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
16502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
16602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    // TODO(edisonn): NYI
16702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    SkPdfTree& treeValue() const {
16802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        static SkPdfTree nyi;
16902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        return nyi;
17002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
17102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
17202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
17302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static void makeBoolean(bool value, SkPdfObject* obj) {
17402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
17502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
17602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj->fObjectType = kBoolean_PdfObjectType;
17702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj->fBooleanValue = value;
17802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
17902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
18002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static SkPdfObject makeBoolean(bool value) {
18102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        SkPdfObject obj;
18202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj.fObjectType = kBoolean_PdfObjectType;
18302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj.fBooleanValue = value;
18402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        return obj;
18502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
18602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
18702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static void makeInteger(int64_t value, SkPdfObject* obj) {
18802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
18902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
19002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj->fObjectType = kInteger_PdfObjectType;
19102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj->fIntegerValue = value;
19202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
19302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
19402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static void makeReal(double value, SkPdfObject* obj) {
19502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
19602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
19702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj->fObjectType = kReal_PdfObjectType;
19802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj->fRealValue = value;
19902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
20002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
20102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static void makeNull(SkPdfObject* obj) {
20202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
20302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
20402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj->fObjectType = kNull_PdfObjectType;
20502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
20602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
20702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static SkPdfObject makeNull() {
20802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        SkPdfObject obj;
20902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj.fObjectType = kNull_PdfObjectType;
21002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        return obj;
21102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
21202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
21302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static SkPdfObject kNull;
21402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
21502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static void makeNumeric(unsigned char* start, unsigned char* end, SkPdfObject* obj) {
21602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
21702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
21802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        // TODO(edisonn): NYI properly
21902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        // if has dot (impl), or exceeds max int, is real, otherwise is int
22002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        bool isInt = true;
22102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        for (unsigned char* current = start; current < end; current++) {
22202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            if (*current == '.') {
22302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                isInt = false;
22402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project                break;
22502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            }
22602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            // TODO(edisonn): report parse issue with numbers like "24asdasd123"
22702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        }
22802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        if (isInt) {
22902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            makeInteger(atol((const char*)start), obj);
23002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        } else {
23102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project            makeReal(atof((const char*)start), obj);
23202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        }
23302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
23402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
23502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static void makeReference(unsigned int id, unsigned int gen, SkPdfObject* obj) {
23602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
23702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
23802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj->fObjectType = kReference_PdfObjectType;
23902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj->fRef.fId = id;
24002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        obj->fRef.fGen = gen;
24102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
24202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
24302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
24402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static void makeString(unsigned char* start, SkPdfObject* obj) {
24502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        makeStringCore(start, strlen((const char*)start), obj, kString_PdfObjectType);
24602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
24702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
24802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static void makeString(unsigned char* start, unsigned char* end, SkPdfObject* obj) {
24902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        makeStringCore(start, end - start, obj, kString_PdfObjectType);
25002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
25102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
25202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static void makeString(unsigned char* start, size_t bytes, SkPdfObject* obj) {
25302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        makeStringCore(start, bytes, obj, kString_PdfObjectType);
25402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
25502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
25602fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
25702fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static void makeHexString(unsigned char* start, SkPdfObject* obj) {
25802fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        makeStringCore(start, strlen((const char*)start), obj, kHexString_PdfObjectType);
25902fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
26002fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
26102fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static void makeHexString(unsigned char* start, unsigned char* end, SkPdfObject* obj) {
26202fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project        makeStringCore(start, end - start, obj, kHexString_PdfObjectType);
26302fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    }
26402fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project
26502fb0aca1189a2c1fd20806c588e9ee80d9755f8The Android Open Source Project    static void makeHexString(unsigned char* start, size_t bytes, SkPdfObject* obj) {
266        makeStringCore(start, bytes, obj, kHexString_PdfObjectType);
267    }
268
269
270    static void makeName(unsigned char* start, SkPdfObject* obj) {
271        makeStringCore(start, strlen((const char*)start), obj, kName_PdfObjectType);
272    }
273
274    static void makeName(unsigned char* start, unsigned char* end, SkPdfObject* obj) {
275        makeStringCore(start, end - start, obj, kName_PdfObjectType);
276    }
277
278    static void makeName(unsigned char* start, size_t bytes, SkPdfObject* obj) {
279        makeStringCore(start, bytes, obj, kName_PdfObjectType);
280    }
281
282
283    static void makeKeyword(unsigned char* start, SkPdfObject* obj) {
284        makeStringCore(start, strlen((const char*)start), obj, kKeyword_PdfObjectType);
285    }
286
287    static void makeKeyword(unsigned char* start, unsigned char* end, SkPdfObject* obj) {
288        makeStringCore(start, end - start, obj, kKeyword_PdfObjectType);
289    }
290
291    static void makeKeyword(unsigned char* start, size_t bytes, SkPdfObject* obj) {
292        makeStringCore(start, bytes, obj, kKeyword_PdfObjectType);
293    }
294
295
296
297    // TODO(edisonn): make the functions to return SkPdfArray, move these functions in SkPdfArray
298    static void makeEmptyArray(SkPdfObject* obj) {
299        SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
300
301        obj->fObjectType = kArray_PdfObjectType;
302        obj->fArray = new SkTDArray<SkPdfObject*>();
303        // return (SkPdfArray*)obj;
304    }
305
306    bool appendInArray(SkPdfObject* obj) {
307        SkASSERT(fObjectType == kArray_PdfObjectType);
308        if (fObjectType != kArray_PdfObjectType) {
309            // TODO(edisonn): report err
310            return false;
311        }
312
313        fArray->push(obj);
314        return true;
315    }
316
317    size_t size() const {
318        SkASSERT(fObjectType == kArray_PdfObjectType);
319
320        return fArray->count();
321    }
322
323    SkPdfObject* objAtAIndex(int i) {
324        SkASSERT(fObjectType == kArray_PdfObjectType);
325
326        return (*fArray)[i];
327    }
328
329    SkPdfObject* removeLastInArray() {
330        SkASSERT(fObjectType == kArray_PdfObjectType);
331
332        SkPdfObject* ret = NULL;
333        fArray->pop(&ret);
334
335        return ret;
336    }
337
338
339    const SkPdfObject* objAtAIndex(int i) const {
340        SkASSERT(fObjectType == kArray_PdfObjectType);
341
342        return (*fArray)[i];
343    }
344
345    SkPdfObject* operator[](int i) {
346        SkASSERT(fObjectType == kArray_PdfObjectType);
347
348        return (*fArray)[i];
349    }
350
351    const SkPdfObject* operator[](int i) const {
352        SkASSERT(fObjectType == kArray_PdfObjectType);
353
354        return (*fArray)[i];
355    }
356
357
358    // TODO(edisonn): make the functions to return SkPdfDictionary, move these functions in SkPdfDictionary
359    static void makeEmptyDictionary(SkPdfObject* obj) {
360        SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
361
362        obj->fObjectType = kDictionary_PdfObjectType;
363        obj->fMap = new SkTDict<SkPdfObject*>(1);
364        obj->fStr.fBuffer = NULL;
365        obj->fStr.fBytes = 0;
366    }
367
368    // TODO(edisonn): get all the possible names from spec, and compute a hash function
369    // that would create no overlaps in the same dictionary
370    // or build a tree of chars that when followed goes to a unique id/index/hash
371    // TODO(edisonn): generate constants like kDictFoo, kNameDict_name
372    // which will be used in code
373    // add function SkPdfFastNameKey key(const char* key);
374    // TODO(edisonn): setting the same key twike, will make the value undefined!
375    bool set(SkPdfObject* key, SkPdfObject* value) {
376        SkASSERT(fObjectType == kDictionary_PdfObjectType);
377        SkASSERT(key->fObjectType == kName_PdfObjectType);
378
379        if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
380            // TODO(edisonn): report err
381            return false;
382        }
383
384        // we rewrite all delimiters and white spaces with '\0', so we expect the end of name to be '\0'
385        SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
386
387        return set(key->fStr.fBuffer, key->fStr.fBytes, value);
388    }
389
390    bool set(const char* key, SkPdfObject* value) {
391        return set((const unsigned char*)key, strlen(key), value);
392    }
393
394    bool set(const unsigned char* key, size_t len, SkPdfObject* value) {
395        SkASSERT(fObjectType == kDictionary_PdfObjectType);
396
397        if (fObjectType != kDictionary_PdfObjectType) {
398            // TODO(edisonn): report err
399            return false;
400        }
401
402        return fMap->set((const char*)key, len, value);
403    }
404
405    SkPdfObject* get(SkPdfObject* key) {
406        SkASSERT(fObjectType == kDictionary_PdfObjectType);
407        SkASSERT(key->fObjectType == kName_PdfObjectType);
408
409        if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
410            // TODO(edisonn): report err
411            return NULL;
412        }
413
414        SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
415
416        return get(key->fStr.fBuffer, key->fStr.fBytes);
417    }
418
419    SkPdfObject* get(const char* key) {
420        return get((const unsigned char*)key, strlen(key));
421    }
422
423    SkPdfObject* get(const unsigned char* key, size_t len) {
424        SkASSERT(fObjectType == kDictionary_PdfObjectType);
425        SkASSERT(key);
426        if (fObjectType != kDictionary_PdfObjectType) {
427            // TODO(edisonn): report err
428            return NULL;
429        }
430        SkPdfObject* ret = NULL;
431        fMap->find((const char*)key, len, &ret);
432        return ret;
433    }
434
435    const SkPdfObject* get(SkPdfObject* key) const {
436        SkASSERT(fObjectType == kDictionary_PdfObjectType);
437        SkASSERT(key->fObjectType == kName_PdfObjectType);
438
439        if (key->fObjectType != kName_PdfObjectType || fObjectType != kDictionary_PdfObjectType) {
440            // TODO(edisonn): report err
441            return NULL;
442        }
443
444        SkASSERT(key->fStr.fBuffer[key->fStr.fBytes] == '\0');
445
446        return get(key->fStr.fBuffer, key->fStr.fBytes);
447    }
448
449    const SkPdfObject* get(const char* key) const {
450        return get((const unsigned char*)key, strlen(key));
451    }
452
453    const SkPdfObject* get(const unsigned char* key, size_t len) const {
454        SkASSERT(fObjectType == kDictionary_PdfObjectType);
455        SkASSERT(key);
456        if (fObjectType != kDictionary_PdfObjectType) {
457            // TODO(edisonn): report err
458            return NULL;
459        }
460        SkPdfObject* ret = NULL;
461        fMap->find((const char*)key, len, &ret);
462        return ret;
463    }
464
465    const SkPdfObject* get(const char* key, const char* abr) const {
466        const SkPdfObject* ret = get(key);
467        // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL
468        // make this distiontion in generator, and remove "" from condition
469        if (ret != NULL || abr == NULL || *abr == '\0') {
470            return ret;
471        }
472        return get(abr);
473    }
474
475    SkPdfObject* get(const char* key, const char* abr) {
476        SkPdfObject* ret = get(key);
477        // TODO(edisonn): / is a valid name, and it might be an abreviation, so "" should not be like NULL
478        // make this distiontion in generator, and remove "" from condition
479        if (ret != NULL || abr == NULL || *abr == '\0') {
480            return ret;
481        }
482        return get(abr);
483    }
484
485    SkPdfDictionary* asDictionary() {
486        SkASSERT(isDictionary());
487        if (!isDictionary()) {
488            return NULL;
489        }
490        return (SkPdfDictionary*) this;
491    }
492
493    const SkPdfDictionary* asDictionary() const {
494        SkASSERT(isDictionary());
495        if (!isDictionary()) {
496            return NULL;
497        }
498        return (SkPdfDictionary*) this;
499    }
500
501
502    bool isReference() const {
503        return fObjectType == kReference_PdfObjectType;
504    }
505
506    bool isBoolean() const {
507        return fObjectType == kBoolean_PdfObjectType;
508    }
509
510    bool isInteger() const {
511        return fObjectType == kInteger_PdfObjectType;
512    }
513private:
514    bool isReal() const {
515        return fObjectType == kReal_PdfObjectType;
516    }
517public:
518    bool isNumber() const {
519        return fObjectType == kInteger_PdfObjectType || fObjectType == kReal_PdfObjectType;
520    }
521
522    bool isKeywordReference() const {
523        return fObjectType == kKeyword_PdfObjectType && fStr.fBytes == 1 && fStr.fBuffer[0] == 'R';
524    }
525
526    bool isKeyword() const {
527        return fObjectType == kKeyword_PdfObjectType;
528    }
529
530    bool isName() const {
531        return fObjectType == kName_PdfObjectType;
532    }
533
534    bool isName(const char* name) const {
535        return fObjectType == kName_PdfObjectType && fStr.fBytes == strlen(name) && strncmp((const char*)fStr.fBuffer, name, fStr.fBytes) == 0;
536    }
537
538    bool isArray() const {
539        return fObjectType == kArray_PdfObjectType;
540    }
541
542    bool isDate() const {
543        return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
544    }
545
546    bool isDictionary() const {
547        return fObjectType == kDictionary_PdfObjectType;
548    }
549
550    bool isFunction() const {
551        return false;  // NYI
552    }
553
554    bool isRectangle() const {
555        return fObjectType == kArray_PdfObjectType && fArray->count() == 4; // NYI + and elems are numbers
556    }
557
558    // TODO(edisonn): has stream .. or is stream ... TBD
559    bool hasStream() const {
560        return isDictionary() && fStr.fBuffer != NULL;
561    }
562
563    // TODO(edisonn): has stream .. or is stream ... TBD
564    const SkPdfStream* getStream() const {
565        return hasStream() ? (const SkPdfStream*)this : NULL;
566    }
567
568    SkPdfStream* getStream() {
569        return hasStream() ? (SkPdfStream*)this : NULL;
570    }
571
572    bool isAnyString() const {
573        return fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType;
574    }
575
576    bool isMatrix() const {
577        return fObjectType == kArray_PdfObjectType && fArray->count() == 6; // NYI + and elems are numbers
578    }
579
580    inline int64_t intValue() const {
581        SkASSERT(fObjectType == kInteger_PdfObjectType);
582
583        if (fObjectType != kInteger_PdfObjectType) {
584            // TODO(edisonn): log err
585            return 0;
586        }
587        return fIntegerValue;
588    }
589private:
590    inline double realValue() const {
591        SkASSERT(fObjectType == kReal_PdfObjectType);
592
593        if (fObjectType != kReal_PdfObjectType) {
594            // TODO(edisonn): log err
595            return 0;
596        }
597        return fRealValue;
598    }
599public:
600    inline double numberValue() const {
601        SkASSERT(isNumber());
602
603        if (!isNumber()) {
604            // TODO(edisonn): log err
605            return 0;
606        }
607        return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue;
608    }
609
610    int referenceId() const {
611        SkASSERT(fObjectType == kReference_PdfObjectType);
612        return fRef.fId;
613    }
614
615    int referenceGeneration() const {
616        SkASSERT(fObjectType == kReference_PdfObjectType);
617        return fRef.fGen;
618    }
619
620    inline const char* nameValue() const {
621        SkASSERT(fObjectType == kName_PdfObjectType);
622
623        if (fObjectType != kName_PdfObjectType) {
624            // TODO(edisonn): log err
625            return "";
626        }
627        return (const char*)fStr.fBuffer;
628    }
629
630    inline const char* stringValue() const {
631        SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
632
633        if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
634            // TODO(edisonn): log err
635            return "";
636        }
637        return (const char*)fStr.fBuffer;
638    }
639
640    // TODO(edisonn): nameValue2 and stringValue2 are used to make code generation easy,
641    // but it is not a performat way to do it, since it will create an extra copy
642    // remove these functions and make code generated faster
643    inline std::string nameValue2() const {
644        SkASSERT(fObjectType == kName_PdfObjectType);
645
646        if (fObjectType != kName_PdfObjectType) {
647            // TODO(edisonn): log err
648            return "";
649        }
650        return (const char*)fStr.fBuffer;
651    }
652
653    inline std::string stringValue2() const {
654        SkASSERT(fObjectType == kString_PdfObjectType || fObjectType == kHexString_PdfObjectType);
655
656        if (fObjectType != kString_PdfObjectType && fObjectType != kHexString_PdfObjectType) {
657            // TODO(edisonn): log err
658            return "";
659        }
660        return (const char*)fStr.fBuffer;
661    }
662
663    inline bool boolValue() const {
664        SkASSERT(fObjectType == kBoolean_PdfObjectType);
665
666        if (fObjectType == kBoolean_PdfObjectType) {
667            // TODO(edisonn): log err
668            return false;
669        }
670        return fBooleanValue;
671    }
672
673    SkRect rectangleValue() const {
674        SkASSERT(isRectangle());
675        if (!isRectangle()) {
676            return SkRect::MakeEmpty();
677        }
678
679        double array[4];
680        for (int i = 0; i < 4; i++) {
681            // TODO(edisonn): version where we could resolve references?
682            const SkPdfObject* elem = objAtAIndex(i);
683            if (elem == NULL || !elem->isNumber()) {
684                // TODO(edisonn): report error
685                return SkRect::MakeEmpty();
686            }
687            array[i] = elem->numberValue();
688        }
689
690        return SkRect::MakeLTRB(SkDoubleToScalar(array[0]),
691                                SkDoubleToScalar(array[1]),
692                                SkDoubleToScalar(array[2]),
693                                SkDoubleToScalar(array[3]));
694    }
695
696    SkMatrix matrixValue() const {
697        SkASSERT(isMatrix());
698        if (!isMatrix()) {
699            return SkMatrix::I();
700        }
701
702        double array[6];
703        for (int i = 0; i < 6; i++) {
704            // TODO(edisonn): version where we could resolve references?
705            const SkPdfObject* elem = objAtAIndex(i);
706            if (elem == NULL || !elem->isNumber()) {
707                // TODO(edisonn): report error
708                return SkMatrix::I();
709            }
710            array[i] = elem->numberValue();
711        }
712
713        return SkMatrixFromPdfMatrix(array);
714    }
715
716    bool filterStream(SkPdfAllocator* allocator);
717
718
719    bool GetFilteredStreamRef(unsigned char** buffer, size_t* len, SkPdfAllocator* allocator) {
720        // TODO(edisonn): add params that couls let the last filter in place if it is jpeg or png to fast load images
721        if (!hasStream()) {
722            return false;
723        }
724
725        filterStream(allocator);
726
727        if (buffer) {
728            *buffer = fStr.fBuffer;
729        }
730
731        if (len) {
732            *len = fStr.fBytes >> 1;  // last bit
733        }
734
735        return true;
736    }
737
738    bool isStreamFiltered() const {
739        return hasStream() && ((fStr.fBytes & 1) == kFilteredStreamBit);
740    }
741
742    bool GetUnfilteredStreamRef(unsigned char** buffer, size_t* len) const {
743        if (isStreamFiltered()) {
744            return false;
745        }
746
747        if (!hasStream()) {
748            return false;
749        }
750
751        if (buffer) {
752            *buffer = fStr.fBuffer;
753        }
754
755        if (len) {
756            *len = fStr.fBytes >> 1;  // remove slast bit
757        }
758
759        return true;
760    }
761
762    bool addStream(unsigned char* buffer, size_t len) {
763        SkASSERT(!hasStream());
764        SkASSERT(isDictionary());
765
766        if (!isDictionary() || hasStream()) {
767            return false;
768        }
769
770        fStr.fBuffer = buffer;
771        fStr.fBytes = (len << 2) + kUnfilteredStreamBit;
772
773        return true;
774    }
775
776    SkString toString() {
777        SkString str;
778        switch (fObjectType) {
779            case kInvalid_PdfObjectType:
780                str.append("Invalid");
781                break;
782
783            case kBoolean_PdfObjectType:
784                str.appendf("Boolean: %s", fBooleanValue ? "true" : "false");
785                break;
786
787            case kInteger_PdfObjectType:
788                str.appendf("Integer: %i", (int)fIntegerValue);
789                break;
790
791            case kReal_PdfObjectType:
792                str.appendf("Real: %f", fRealValue);
793                break;
794
795            case kString_PdfObjectType:
796                str.appendf("String, len() = %u: ", (unsigned int)fStr.fBytes);
797                str.append((const char*)fStr.fBuffer, fStr.fBytes);
798                break;
799
800            case kHexString_PdfObjectType:
801                str.appendf("HexString, len() = %u: ", (unsigned int)fStr.fBytes);
802                str.append((const char*)fStr.fBuffer, fStr.fBytes);
803                break;
804
805            case kName_PdfObjectType:
806                str.appendf("Name, len() = %u: ", (unsigned int)fStr.fBytes);
807                str.append((const char*)fStr.fBuffer, fStr.fBytes);
808                break;
809
810            case kKeyword_PdfObjectType:
811                str.appendf("Keyword, len() = %u: ", (unsigned int)fStr.fBytes);
812                str.append((const char*)fStr.fBuffer, fStr.fBytes);
813                break;
814
815            case kArray_PdfObjectType:
816                str.append("Array, size() = %i [", size());
817                for (unsigned int i = 0; i < size(); i++) {
818                    str.append(objAtAIndex(i)->toString());
819                }
820                str.append("]");
821                break;
822
823            case kDictionary_PdfObjectType:
824                // TODO(edisonn): NYI
825                str.append("Dictionary: NYI");
826                if (hasStream()) {
827                    str.append(" HAS_STREAM");
828                }
829                break;
830
831            case kNull_PdfObjectType:
832                str = "NULL";
833                break;
834
835            case kReference_PdfObjectType:
836                str.appendf("Reference: %i %i", fRef.fId, fRef.fGen);
837                break;
838
839            case kUndefined_PdfObjectType:
840                str = "Undefined";
841                break;
842
843            default:
844                str = "Internal Error Object Type";
845                break;
846        }
847
848        return str;
849    }
850
851private:
852    static void makeStringCore(unsigned char* start, SkPdfObject* obj, ObjectType type) {
853        makeStringCore(start, strlen((const char*)start), obj, type);
854    }
855
856    static void makeStringCore(unsigned char* start, unsigned char* end, SkPdfObject* obj, ObjectType type) {
857        makeStringCore(start, end - start, obj, type);
858    }
859
860    static void makeStringCore(unsigned char* start, size_t bytes, SkPdfObject* obj, ObjectType type) {
861        SkASSERT(obj->fObjectType == kInvalid_PdfObjectType);
862
863        obj->fObjectType = type;
864        obj->fStr.fBuffer = start;
865        obj->fStr.fBytes = bytes;
866    }
867
868    bool applyFilter(const char* name, SkPdfAllocator* allocator);
869    bool applyFlateDecodeFilter(SkPdfAllocator* allocator);
870    bool applyDCTDecodeFilter(SkPdfAllocator* allocator);
871};
872
873class SkPdfStream : public SkPdfObject {};
874class SkPdfArray : public SkPdfObject {};
875class SkPdfString : public SkPdfObject {};
876class SkPdfHexString : public SkPdfObject {};
877class SkPdfInteger : public SkPdfObject {};
878class SkPdfReal : public SkPdfObject {};
879class SkPdfNumber : public SkPdfObject {};
880
881class SkPdfName : public SkPdfObject {
882    SkPdfName() : SkPdfObject() {
883        SkPdfObject::makeName((unsigned char*)"", this);
884    }
885public:
886    SkPdfName(char* name) : SkPdfObject() {
887        this->makeName((unsigned char*)name, this);
888    }
889};
890
891#endif  // EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFOBJECT_H_
892