diff options
author | halcanary <halcanary@google.com> | 2015-04-25 06:45:07 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-25 06:45:07 -0700 |
commit | 130444fdaf737c5931a934018ab50b0c91a3499e (patch) | |
tree | 9e853af14d9b8b3e38b344340379b74e1a27e475 /src/pdf/SkPDFTypes.h | |
parent | 8e71d38126df1ed40ee88107e681c8b62f726e30 (diff) |
SkPDF: Refactor SkPDFObject heiararchy.
Flatten and use a tagged union type
Δmemory ~= -2.4% ± 0.5%
Δtime ~= -1.2% ± 0.2%
BUG=skia:3585
Review URL: https://codereview.chromium.org/1069103003
Diffstat (limited to 'src/pdf/SkPDFTypes.h')
-rw-r--r-- | src/pdf/SkPDFTypes.h | 422 |
1 files changed, 210 insertions, 212 deletions
diff --git a/src/pdf/SkPDFTypes.h b/src/pdf/SkPDFTypes.h index 76e191134c..f258e384e5 100644 --- a/src/pdf/SkPDFTypes.h +++ b/src/pdf/SkPDFTypes.h @@ -1,4 +1,3 @@ - /* * Copyright 2010 The Android Open Source Project * @@ -10,7 +9,6 @@ #ifndef SkPDFTypes_DEFINED #define SkPDFTypes_DEFINED -#include "SkPDFTypes.h" #include "SkRefCnt.h" #include "SkScalar.h" #include "SkString.h" @@ -28,10 +26,11 @@ class SkWStream; 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: - SK_DECLARE_INST_COUNT(SkPDFObject) + SK_DECLARE_INST_COUNT(SkPDFObject); /** Subclasses must implement this method to print the object to the * PDF file. @@ -55,170 +54,191 @@ private: typedef SkRefCnt INHERITED; }; -/** \class SkPDFObjRef +//////////////////////////////////////////////////////////////////////////////// - An indirect reference to a PDF object. -*/ -class SkPDFObjRef : public SkPDFObject { +/** + A SkPDFUnion is a non-virtualized implementation of the + non-compound, non-specialized PDF Object types: Name, String, + Number, Boolean. + */ +class SkPDFUnion { public: - SK_DECLARE_INST_COUNT(SkPDFObjRef) + // 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); - /** Create a reference to an existing SkPDFObject. - * @param obj The object to reference. - */ - explicit SkPDFObjRef(SkPDFObject* obj); - virtual ~SkPDFObjRef(); + ~SkPDFUnion(); - // The SkPDFObject interface. - virtual void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) override; - virtual void addResources(SkPDFObjNumMap*, - const SkPDFSubstituteMap&) const override; + /** The following nine functions are the standard way of creating + SkPDFUnion objects. */ -private: - SkAutoTUnref<SkPDFObject> fObj; + static SkPDFUnion Int(int32_t); - typedef SkPDFObject INHERITED; -}; + static SkPDFUnion Bool(bool); -/** \class SkPDFInt + static SkPDFUnion Scalar(SkScalar); - An integer object in a PDF. -*/ -class SkPDFInt : public SkPDFObject { -public: - SK_DECLARE_INST_COUNT(SkPDFInt) + /** 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"); */ - /** Create a PDF integer (usually for indirect reference purposes). - * @param value An integer value between 2^31 - 1 and -2^31. - */ - explicit SkPDFInt(int32_t value); - virtual ~SkPDFInt(); + /** 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*); - // The SkPDFObject interface. - virtual void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) override; + /** SkPDFUnion::String will encode the passed string. This will + not copy the name. */ + static SkPDFUnion String(const char*); -private: - int32_t fValue; + /** 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&); - typedef SkPDFObject INHERITED; -}; + /** SkPDFUnion::String will encode the passed string. */ + static SkPDFUnion String(const SkString&); -/** \class SkPDFBool + /** 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*); - An boolean value in a PDF. -*/ -class SkPDFBool : public SkPDFObject { -public: - SK_DECLARE_INST_COUNT(SkPDFBool) + /** 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*); - /** Create a PDF boolean. - * @param value true or false. - */ - explicit SkPDFBool(bool value); - virtual ~SkPDFBool(); + /** These two non-virtual methods mirror SkPDFObject's + corresponding virtuals. */ + void emitObject(SkWStream*, + const SkPDFObjNumMap&, + const SkPDFSubstituteMap&) const; + void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const; - // The SkPDFObject interface. - virtual void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) override; + bool isName() const; private: - bool fValue; + 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; - typedef SkPDFObject INHERITED; + 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; }; +SK_COMPILE_ASSERT(sizeof(SkString) == sizeof(void*), SkString_size); -/** \class SkPDFScalar +//////////////////////////////////////////////////////////////////////////////// - A real number object in a PDF. -*/ -class SkPDFScalar : public SkPDFObject { +/** This class is a SkPDFUnion with SkPDFObject virtuals attached. */ +// TODO(halcanary): 99% of the uses of this class should be +// transitioned to using a bare SkPDFUnion inside an array or dict. +class SkPDFAtom : public SkPDFObject { public: - SK_DECLARE_INST_COUNT(SkPDFScalar) + void emitObject(SkWStream* stream, + const SkPDFObjNumMap& objNumMap, + const SkPDFSubstituteMap& substitutes) final; + void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const final; - /** Create a PDF real number. - * @param value A real value. - */ - explicit SkPDFScalar(SkScalar value); - virtual ~SkPDFScalar(); - - static void Append(SkScalar value, SkWStream* stream); - - // The SkPDFObject interface. - virtual void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) override; +protected: + SkPDFAtom(SkPDFUnion&& v) : fValue(v.move()) {} private: - SkScalar fValue; - + const SkPDFUnion fValue; typedef SkPDFObject INHERITED; }; -/** \class SkPDFString +/** The following six classes exist only to ease transition to SkPDFUnion. */ +class SkPDFObjRef : public SkPDFAtom { +public: + SK_DECLARE_INST_COUNT(SkPDFObjRef); + explicit SkPDFObjRef(SkPDFObject* obj) + : INHERITED(SkPDFUnion::ObjRef(SkRef(obj))) {} + typedef SkPDFAtom INHERITED; +}; - A string object in a PDF. -*/ -class SkPDFString : public SkPDFObject { +class SkPDFInt : public SkPDFAtom { public: - SK_DECLARE_INST_COUNT(SkPDFString) + SK_DECLARE_INST_COUNT(SkPDFInt); + explicit SkPDFInt(int32_t value) : INHERITED(SkPDFUnion::Int(value)) {} + typedef SkPDFAtom INHERITED; +}; - /** Create a PDF string. Maximum length (in bytes) is 65,535. - * @param value A string value. - */ - explicit SkPDFString(const char value[]); - explicit SkPDFString(const SkString& value); +class SkPDFBool : public SkPDFAtom { +public: + SK_DECLARE_INST_COUNT(SkPDFBool); + explicit SkPDFBool(bool value) : INHERITED(SkPDFUnion::Bool(value)) {} + typedef SkPDFAtom INHERITED; +}; - virtual ~SkPDFString(); +class SkPDFScalar : public SkPDFAtom { +public: + SK_DECLARE_INST_COUNT(SkPDFScalar); + explicit SkPDFScalar(SkScalar value) + : INHERITED(SkPDFUnion::Scalar(value)) {} + static void Append(SkScalar value, SkWStream* stream); + typedef SkPDFAtom INHERITED; +}; - // The SkPDFObject interface. - virtual void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) override; +class SkPDFString : public SkPDFAtom { +public: + SK_DECLARE_INST_COUNT(SkPDFString); + explicit SkPDFString(const char value[]) + : INHERITED(SkPDFUnion::String(value)) {} + explicit SkPDFString(const SkString& value) + : INHERITED(SkPDFUnion::String(value)) {} static SkString FormatString(const char* input, size_t len); -private: - static const size_t kMaxLen = 65535; - const SkString fValue; + static const size_t kMaxLen = 65535; - typedef SkPDFObject INHERITED; +private: + typedef SkPDFAtom INHERITED; }; -/** \class SkPDFName - - A name object in a PDF. -*/ -class SkPDFName : public SkPDFObject { +class SkPDFName : public SkPDFAtom { public: - SK_DECLARE_INST_COUNT(SkPDFName) - - /** Create a PDF name object. Maximum length is 127 bytes. - * @param value The name. - */ - explicit SkPDFName(const char name[]); - explicit SkPDFName(const SkString& name); - virtual ~SkPDFName(); - - bool operator==(const SkPDFName& b) const; - - // The SkPDFObject interface. - virtual void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) override; + SK_DECLARE_INST_COUNT(SkPDFName); + /** Create a PDF name object. Maximum length is 127 bytes. */ + explicit SkPDFName(const char name[]) + : INHERITED(SkPDFUnion::Name(SkString(name))) {} + explicit SkPDFName(const SkString& name) + : INHERITED(SkPDFUnion::Name(name)) {} -private: static const size_t kMaxLen = 127; - const SkString fValue; - - static SkString FormatName(const SkString& input); - - typedef SkPDFObject INHERITED; +private: + typedef SkPDFAtom INHERITED; }; /** \class SkPDFArray @@ -229,6 +249,8 @@ class SkPDFArray : public SkPDFObject { public: SK_DECLARE_INST_COUNT(SkPDFArray) + static const int kMaxLen = 8191; + /** Create a PDF array. Maximum length is 8191. */ SkPDFArray(); @@ -243,7 +265,7 @@ public: /** The size of the array. */ - int size() { return fValue.count(); } + int size() const; /** Preallocate space for the given number of entries. * @param length The number of array slots to preallocate. @@ -254,27 +276,26 @@ public: * @param value The value to add to the array. * @return The value argument is returned. */ + // DEPRECATED SkPDFObject* append(SkPDFObject* value); - /** Creates a SkPDFInt object and appends it to the array. - * @param value The value to add to the array. - */ - void appendInt(int32_t value); - - /** Creates a SkPDFScalar object and appends it to the array. + /** Appends a value to the end of the array. * @param value The value to add to the array. */ - void appendScalar(SkScalar value); - - /** Creates a SkPDFName object and appends it to the array. - * @param value The value to add to the array. - */ - void appendName(const char name[]); + 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: - static const int kMaxLen = 8191; - SkTDArray<SkPDFObject*> fValue; - + SkTDArray<SkPDFUnion> fValues; + void append(SkPDFUnion&& value); typedef SkPDFObject INHERITED; }; @@ -313,104 +334,53 @@ public: * @param value The value for this dictionary entry. * @return The value argument is returned. */ + // DEPRECATED SkPDFObject* insert(SkPDFName* key, SkPDFObject* value); + // DEPRECATED + SkPDFObject* insert(const char key[], SkPDFObject* value); - /** Add the value to the dictionary with the given key. Refs value. The - * method will create the SkPDFName object. + /** 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. - * @return The value argument is returned. */ - SkPDFObject* insert(const char key[], SkPDFObject* value); + 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 int to the dictionary with the given key. + /** Add the value to the dictionary with the given key. * @param key The text of the key for this dictionary entry. - * @param value The int value for this dictionary entry. + * @param value The value for this dictionary entry. */ void insertInt(const char key[], int32_t value); - - /** - * Calls insertInt() but asserts in debug builds that the value can be represented - * by an int32_t. - */ - void insertInt(const char key[], size_t value) { - this->insertInt(key, SkToS32(value)); - } - - /** Add the scalar to the dictionary with the given key. - * @param key The text of the key for this dictionary entry. - * @param value The scalar value for this dictionary entry. - */ + void insertInt(const char key[], size_t value); void insertScalar(const char key[], SkScalar value); - - /** Add the name to the dictionary with the given key. - * @param key The text of the key for this dictionary entry. - * @param name The name for this dictionary entry. - */ - void insertName(const char key[], const char name[]); - - /** Add the name to the dictionary with the given key. - * @param key The text of the key for this dictionary entry. - * @param name The name for this dictionary entry. - */ - void insertName(const char key[], const SkString& name) { - this->insertName(key, name.c_str()); - } + 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(); -protected: - /** Use to remove a single key from the dictionary. - */ - void remove(const char key[]); - - /** Insert references to all of the key-value pairs from the other - * dictionary into this one. - */ - void mergeFrom(const SkPDFDict& other); - private: - struct Rec { - SkPDFName* key; - SkPDFObject* value; - Rec(SkPDFName* k, SkPDFObject* v) : key(k), value(v) {} + struct Record { + SkPDFUnion fKey; + SkPDFUnion fValue; }; - + SkTDArray<Record> fRecords; static const int kMaxLen = 4095; - SkTDArray<struct Rec> fValue; - - SkPDFObject* append(SkPDFName* key, SkPDFObject* value); + void set(const SkPDFUnion& name, const SkPDFUnion& value); + void set(SkPDFUnion&& name, SkPDFUnion&& value); typedef SkPDFObject INHERITED; }; //////////////////////////////////////////////////////////////////////////////// -/** \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; - -private: - SkTHashMap<SkPDFObject*, SkPDFObject*> fSubstituteMap; -}; - /** \class SkPDFObjNumMap The PDF Object Number Map manages object numbers. It is used to @@ -436,4 +406,32 @@ private: 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; +}; + #endif |