| /* |
| * Copyright 2010 The Android Open Source Project |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| |
| #ifndef SkPDFTypes_DEFINED |
| #define SkPDFTypes_DEFINED |
| |
| #include "SkRefCnt.h" |
| #include "SkScalar.h" |
| #include "SkStream.h" |
| #include "SkString.h" |
| #include "SkTDArray.h" |
| #include "SkTHash.h" |
| #include "SkTypes.h" |
| |
| class SkPDFObjNumMap; |
| class SkPDFObject; |
| class SkPDFSubstituteMap; |
| |
| #ifdef SK_PDF_IMAGE_STATS |
| #include "SkAtomics.h" |
| #endif |
| |
| /** \class SkPDFObject |
| |
| A PDF Object is the base class for primitive elements in a PDF file. A |
| common subtype is used to ease the use of indirect object references, |
| which are common in the PDF format. |
| |
| */ |
| class SkPDFObject : public SkRefCnt { |
| public: |
| /** Subclasses must implement this method to print the object to the |
| * PDF file. |
| * @param catalog The object catalog to use. |
| * @param stream The writable output stream to send the output to. |
| */ |
| // TODO(halcanary): make this method const |
| virtual void emitObject(SkWStream* stream, |
| const SkPDFObjNumMap& objNumMap, |
| const SkPDFSubstituteMap& substitutes) const = 0; |
| |
| /** |
| * Adds all transitive dependencies of this object to the |
| * catalog. Implementations should respect the catalog's object |
| * substitution map. |
| */ |
| virtual void addResources(SkPDFObjNumMap* catalog, |
| const SkPDFSubstituteMap& substitutes) const {} |
| |
| private: |
| typedef SkRefCnt INHERITED; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| A SkPDFUnion is a non-virtualized implementation of the |
| non-compound, non-specialized PDF Object types: Name, String, |
| Number, Boolean. |
| */ |
| class SkPDFUnion { |
| public: |
| // u.move() is analogous to std::move(u). It returns an rvalue. |
| SkPDFUnion move() { return static_cast<SkPDFUnion&&>(*this); } |
| // Move contstructor and assignemnt operator destroy the argument |
| // and steal their references (if needed). |
| SkPDFUnion(SkPDFUnion&& other); |
| SkPDFUnion& operator=(SkPDFUnion&& other); |
| |
| ~SkPDFUnion(); |
| |
| /** The following nine functions are the standard way of creating |
| SkPDFUnion objects. */ |
| |
| static SkPDFUnion Int(int32_t); |
| |
| static SkPDFUnion Int(size_t v) { return SkPDFUnion::Int(SkToS32(v)); } |
| |
| static SkPDFUnion Bool(bool); |
| |
| static SkPDFUnion Scalar(SkScalar); |
| |
| /** These two functions do NOT take ownership of ptr, and do NOT |
| copy the string. Suitable for passing in static const |
| strings. For example: |
| SkPDFUnion n = SkPDFUnion::Name("Length"); |
| SkPDFUnion u = SkPDFUnion::String("Identity"); */ |
| |
| /** SkPDFUnion::Name(const char*) assumes that the passed string |
| is already a valid name (that is: it has no control or |
| whitespace characters). This will not copy the name. */ |
| static SkPDFUnion Name(const char*); |
| |
| /** SkPDFUnion::String will encode the passed string. This will |
| not copy the name. */ |
| static SkPDFUnion String(const char*); |
| |
| /** SkPDFUnion::Name(const SkString&) does not assume that the |
| passed string is already a valid name and it will escape the |
| string. */ |
| static SkPDFUnion Name(const SkString&); |
| |
| /** SkPDFUnion::String will encode the passed string. */ |
| static SkPDFUnion String(const SkString&); |
| |
| /** This function DOES take ownership of the object. E.g. |
| SkAutoTUnref<SkPDFDict> dict(new SkPDFDict); |
| dict->insert(.....); |
| SkPDFUnion u = SkPDFUnion::Object(dict.detach()) */ |
| static SkPDFUnion Object(SkPDFObject*); |
| |
| /** This function DOES take ownership of the object. E.g. |
| SkAutoTUnref<SkPDFBitmap> image( |
| SkPDFBitmap::Create(fCanon, bitmap)); |
| SkPDFUnion u = SkPDFUnion::ObjRef(image.detach()) */ |
| static SkPDFUnion ObjRef(SkPDFObject*); |
| |
| /** These two non-virtual methods mirror SkPDFObject's |
| corresponding virtuals. */ |
| void emitObject(SkWStream*, |
| const SkPDFObjNumMap&, |
| const SkPDFSubstituteMap&) const; |
| void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const; |
| |
| bool isName() const; |
| |
| private: |
| union { |
| int32_t fIntValue; |
| bool fBoolValue; |
| SkScalar fScalarValue; |
| const char* fStaticString; |
| char fSkString[sizeof(SkString)]; |
| SkPDFObject* fObject; |
| }; |
| enum class Type : char { |
| /** It is an error to call emitObject() or addResources() on an |
| kDestroyed object. */ |
| kDestroyed = 0, |
| kInt, |
| kBool, |
| kScalar, |
| kName, |
| kString, |
| kNameSkS, |
| kStringSkS, |
| kObjRef, |
| kObject, |
| }; |
| Type fType; |
| |
| SkPDFUnion(Type); |
| // We do not now need copy constructor and copy assignment, so we |
| // will disable this functionality. |
| SkPDFUnion& operator=(const SkPDFUnion&) = delete; |
| SkPDFUnion(const SkPDFUnion&) = delete; |
| }; |
| static_assert(sizeof(SkString) == sizeof(void*), "SkString_size"); |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| #if 0 // Enable if needed. |
| /** This class is a SkPDFUnion with SkPDFObject virtuals attached. |
| The only use case of this is when a non-compound PDF object is |
| referenced indirectly. */ |
| class SkPDFAtom : public SkPDFObject { |
| public: |
| void emitObject(SkWStream* stream, |
| const SkPDFObjNumMap& objNumMap, |
| const SkPDFSubstituteMap& substitutes) final; |
| void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const final; |
| SkPDFAtom(SkPDFUnion&& v) : fValue(v.move()) {} |
| |
| private: |
| const SkPDFUnion fValue; |
| typedef SkPDFObject INHERITED; |
| }; |
| #endif // 0 |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| /** \class SkPDFArray |
| |
| An array object in a PDF. |
| */ |
| class SkPDFArray : public SkPDFObject { |
| public: |
| static const int kMaxLen = 8191; |
| |
| /** Create a PDF array. Maximum length is 8191. |
| */ |
| SkPDFArray(); |
| virtual ~SkPDFArray(); |
| |
| // The SkPDFObject interface. |
| void emitObject(SkWStream* stream, |
| const SkPDFObjNumMap& objNumMap, |
| const SkPDFSubstituteMap& substitutes) const override; |
| void addResources(SkPDFObjNumMap*, |
| const SkPDFSubstituteMap&) const override; |
| |
| /** The size of the array. |
| */ |
| int size() const; |
| |
| /** Preallocate space for the given number of entries. |
| * @param length The number of array slots to preallocate. |
| */ |
| void reserve(int length); |
| |
| /** Appends a value to the end of the array. |
| * @param value The value to add to the array. |
| */ |
| void appendInt(int32_t); |
| void appendBool(bool); |
| void appendScalar(SkScalar); |
| void appendName(const char[]); |
| void appendName(const SkString&); |
| void appendString(const char[]); |
| void appendString(const SkString&); |
| /** appendObject and appendObjRef take ownership of the passed object */ |
| void appendObject(SkPDFObject*); |
| void appendObjRef(SkPDFObject*); |
| |
| private: |
| SkTDArray<SkPDFUnion> fValues; |
| void append(SkPDFUnion&& value); |
| typedef SkPDFObject INHERITED; |
| }; |
| |
| /** \class SkPDFDict |
| |
| A dictionary object in a PDF. |
| */ |
| class SkPDFDict : public SkPDFObject { |
| public: |
| /** Create a PDF dictionary. Maximum number of entries is 4095. |
| */ |
| SkPDFDict(); |
| |
| /** Create a PDF dictionary with a Type entry. |
| * @param type The value of the Type entry. |
| */ |
| explicit SkPDFDict(const char type[]); |
| |
| virtual ~SkPDFDict(); |
| |
| // The SkPDFObject interface. |
| void emitObject(SkWStream* stream, |
| const SkPDFObjNumMap& objNumMap, |
| const SkPDFSubstituteMap& substitutes) const override; |
| void addResources(SkPDFObjNumMap*, |
| const SkPDFSubstituteMap&) const override; |
| |
| /** The size of the dictionary. |
| */ |
| int size() const; |
| |
| /** Add the value to the dictionary with the given key. Takes |
| * ownership of the object. |
| * @param key The text of the key for this dictionary entry. |
| * @param value The value for this dictionary entry. |
| */ |
| void insertObject(const char key[], SkPDFObject* value); |
| void insertObject(const SkString& key, SkPDFObject* value); |
| void insertObjRef(const char key[], SkPDFObject* value); |
| void insertObjRef(const SkString& key, SkPDFObject* value); |
| |
| /** Add the value to the dictionary with the given key. |
| * @param key The text of the key for this dictionary entry. |
| * @param value The value for this dictionary entry. |
| */ |
| void insertBool(const char key[], bool value); |
| void insertInt(const char key[], int32_t value); |
| void insertInt(const char key[], size_t value); |
| void insertScalar(const char key[], SkScalar value); |
| void insertName(const char key[], const char nameValue[]); |
| void insertName(const char key[], const SkString& nameValue); |
| void insertString(const char key[], const char value[]); |
| void insertString(const char key[], const SkString& value); |
| |
| /** Remove all entries from the dictionary. |
| */ |
| void clear(); |
| |
| /** Emit the dictionary, without the "<<" and ">>". |
| */ |
| void emitAll(SkWStream* stream, |
| const SkPDFObjNumMap& objNumMap, |
| const SkPDFSubstituteMap& substitutes) const; |
| |
| private: |
| struct Record { |
| SkPDFUnion fKey; |
| SkPDFUnion fValue; |
| }; |
| SkTDArray<Record> fRecords; |
| static const int kMaxLen = 4095; |
| |
| void set(SkPDFUnion&& name, SkPDFUnion&& value); |
| |
| typedef SkPDFObject INHERITED; |
| }; |
| |
| /** \class SkPDFSharedStream |
| |
| This class takes an asset and assumes that it is backed by |
| long-lived shared data (for example, an open file |
| descriptor). That is: no memory savings can be made by holding on |
| to a compressed version instead. |
| */ |
| class SkPDFSharedStream : public SkPDFObject { |
| public: |
| // Takes ownership of asset. |
| SkPDFSharedStream(SkStreamAsset* data) : fAsset(data), fDict(new SkPDFDict) { SkASSERT(data); } |
| SkPDFDict* dict() { return fDict; } |
| void emitObject(SkWStream*, |
| const SkPDFObjNumMap&, |
| const SkPDFSubstituteMap&) const override; |
| void addResources(SkPDFObjNumMap*, |
| const SkPDFSubstituteMap&) const override; |
| |
| private: |
| SkAutoTDelete<SkStreamAsset> fAsset; |
| SkAutoTUnref<SkPDFDict> fDict; |
| typedef SkPDFObject INHERITED; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| /** \class SkPDFObjNumMap |
| |
| The PDF Object Number Map manages object numbers. It is used to |
| create the PDF cross reference table. |
| */ |
| class SkPDFObjNumMap : SkNoncopyable { |
| public: |
| /** Add the passed object to the catalog. |
| * @param obj The object to add. |
| * @return True iff the object was not already added to the catalog. |
| */ |
| bool addObject(SkPDFObject* obj); |
| |
| /** Get the object number for the passed object. |
| * @param obj The object of interest. |
| */ |
| int32_t getObjectNumber(SkPDFObject* obj) const; |
| |
| const SkTDArray<SkPDFObject*>& objects() const { return fObjects; } |
| |
| private: |
| SkTDArray<SkPDFObject*> fObjects; |
| SkTHashMap<SkPDFObject*, int32_t> fObjectNumbers; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| /** \class SkPDFSubstituteMap |
| |
| The PDF Substitute Map manages substitute objects and owns the |
| substitutes. |
| */ |
| class SkPDFSubstituteMap : SkNoncopyable { |
| public: |
| ~SkPDFSubstituteMap(); |
| /** Set substitute object for the passed object. |
| Refs substitute. |
| */ |
| void setSubstitute(SkPDFObject* original, SkPDFObject* substitute); |
| |
| /** Find and return any substitute object set for the passed object. If |
| * there is none, return the passed object. |
| */ |
| SkPDFObject* getSubstitute(SkPDFObject* object) const; |
| |
| SkPDFObject* operator()(SkPDFObject* o) const { |
| return this->getSubstitute(o); |
| } |
| |
| private: |
| SkTHashMap<SkPDFObject*, SkPDFObject*> fSubstituteMap; |
| }; |
| |
| #ifdef SK_PDF_IMAGE_STATS |
| extern SkAtomic<int> gDrawImageCalls; |
| extern SkAtomic<int> gJpegImageObjects; |
| extern SkAtomic<int> gRegularImageObjects; |
| extern void SkPDFImageDumpStats(); |
| #endif // SK_PDF_IMAGE_STATS |
| |
| #endif |