diff options
author | halcanary <halcanary@google.com> | 2015-04-01 13:31:19 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-01 13:31:19 -0700 |
commit | be27a118c277af23377d38e9b3bfd3fcc276114f (patch) | |
tree | 1898203654addbbb8cf77f1b3231d50c1860ead3 | |
parent | 03e5161bed3bdfa0d9fb0867378237bac7d8bd12 (diff) |
SkPDF: SkPDFGraphicState Lookup hashtabled
In Release, running `dm --src skp --config pdf`, I get a
speedup of about 1.2%.
SkPDFGraphicState class:
- Holds the subset of SkPaint that maps to a PDF Graphics
State
- These fields are easily comparable, making hashtable
comparisons easy.
SkPDFCanon:
- findGraphicState() takes a SkPDFGraphicState, not a SkPaint
- fGraphicStateRecords is a SkHashSet, not a SkTDArray
SkPDFGraphicState:
- mode_for_pdf() replaces logic inside equivalent(), but is
only called once per lookup.
- emitObject() no longer modifies the SkPDFGraphicState to
cache the SkPDFDict stucture. (Since it is de-duped,
this get no speedup).
- Static Functions that don't use the canon return a plain
SkPDFDict now. No need for fPopulated.
SkTHash.h
- SkHashSet::forall added
SkPDFDevice; SkPDFShader
- Updated for new SkPDFGraphicState interface.
BUG=skia:3585
Review URL: https://codereview.chromium.org/1046293002
-rw-r--r-- | src/core/SkTHash.h | 6 | ||||
-rw-r--r-- | src/pdf/SkPDFCanon.cpp | 16 | ||||
-rw-r--r-- | src/pdf/SkPDFCanon.h | 22 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 5 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.h | 4 | ||||
-rw-r--r-- | src/pdf/SkPDFGraphicState.cpp | 210 | ||||
-rw-r--r-- | src/pdf/SkPDFGraphicState.h | 47 | ||||
-rw-r--r-- | src/pdf/SkPDFShader.cpp | 4 |
8 files changed, 158 insertions, 156 deletions
diff --git a/src/core/SkTHash.h b/src/core/SkTHash.h index c4bd3b6161..3637c53c46 100644 --- a/src/core/SkTHash.h +++ b/src/core/SkTHash.h @@ -237,6 +237,12 @@ public: // This pointer remains valid until the next call to add(). const T* find(const T& item) const { return fTable.find(item); } + // Call fn on every item in the set. You may not mutate anything. + template <typename Fn> // f(T), f(const T&) + void foreach (Fn&& fn) const { + fTable.foreach (fn); + } + private: struct Traits { static const T& GetKey(const T& item) { return item; } diff --git a/src/pdf/SkPDFCanon.cpp b/src/pdf/SkPDFCanon.cpp index eda255051a..b6187cbb33 100644 --- a/src/pdf/SkPDFCanon.cpp +++ b/src/pdf/SkPDFCanon.cpp @@ -8,7 +8,6 @@ #include "SkPDFBitmap.h" #include "SkPDFCanon.h" #include "SkPDFFont.h" -#include "SkPDFGraphicState.h" #include "SkPDFShader.h" //////////////////////////////////////////////////////////////////////////////// @@ -24,7 +23,7 @@ void SkPDFCanon::reset() { fAlphaShaderRecords.reset(); fImageShaderRecords.unrefAll(); fImageShaderRecords.reset(); - fGraphicStateRecords.unrefAll(); + fGraphicStateRecords.foreach ([](WrapGS w) { w.fPtr->unref(); }); fGraphicStateRecords.reset(); fBitmapRecords.unrefAll(); fBitmapRecords.reset(); @@ -107,12 +106,17 @@ void SkPDFCanon::addImageShader(SkPDFImageShader* pdfShader) { //////////////////////////////////////////////////////////////////////////////// -SkPDFGraphicState* SkPDFCanon::findGraphicState(const SkPaint& paint) const { - return find_item(fGraphicStateRecords, paint); +const SkPDFGraphicState* SkPDFCanon::findGraphicState( + const SkPDFGraphicState& key) const { + const WrapGS* ptr = fGraphicStateRecords.find(WrapGS(&key)); + return ptr ? ptr->fPtr : NULL; } -void SkPDFCanon::addGraphicState(SkPDFGraphicState* state) { - fGraphicStateRecords.push(SkRef(state)); +void SkPDFCanon::addGraphicState(const SkPDFGraphicState* state) { + SkASSERT(state); + WrapGS w(SkRef(state)); + SkASSERT(!fGraphicStateRecords.contains(w)); + fGraphicStateRecords.add(w); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/pdf/SkPDFCanon.h b/src/pdf/SkPDFCanon.h index d0bef27ed6..5198e7b0ac 100644 --- a/src/pdf/SkPDFCanon.h +++ b/src/pdf/SkPDFCanon.h @@ -7,12 +7,13 @@ #ifndef SkPDFCanon_DEFINED #define SkPDFCanon_DEFINED +#include "SkPDFGraphicState.h" #include "SkPDFShader.h" #include "SkTDArray.h" +#include "SkTHash.h" class SkBitmap; class SkPDFFont; -class SkPDFGraphicState; class SkPDFBitmap; class SkPaint; @@ -56,8 +57,8 @@ public: SkPDFImageShader* findImageShader(const SkPDFShader::State&) const; void addImageShader(SkPDFImageShader*); - SkPDFGraphicState* findGraphicState(const SkPaint&) const; - void addGraphicState(SkPDFGraphicState*); + const SkPDFGraphicState* findGraphicState(const SkPDFGraphicState&) const; + void addGraphicState(const SkPDFGraphicState*); SkPDFBitmap* findBitmap(const SkBitmap&) const; void addBitmap(SkPDFBitmap*); @@ -76,7 +77,20 @@ private: SkTDArray<SkPDFImageShader*> fImageShaderRecords; - SkTDArray<SkPDFGraphicState*> fGraphicStateRecords; + struct WrapGS { + explicit WrapGS(const SkPDFGraphicState* ptr = NULL) : fPtr(ptr) {} + const SkPDFGraphicState* fPtr; + bool operator==(const WrapGS& rhs) const { + SkASSERT(fPtr); + SkASSERT(rhs.fPtr); + return *fPtr == *rhs.fPtr; + } + static uint32_t Hash(const WrapGS& w) { + SkASSERT(w.fPtr); + return w.fPtr->hash(); + } + }; + SkTHashSet<WrapGS, WrapGS::Hash> fGraphicStateRecords; SkTDArray<SkPDFBitmap*> fBitmapRecords; }; diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 87555a8111..ced075ebf9 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -1569,8 +1569,7 @@ void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, return; } - SkAutoTUnref<SkPDFGraphicState> sMaskGS( - SkPDFGraphicState::GetSMaskGraphicState( + SkAutoTUnref<SkPDFObject> sMaskGS(SkPDFGraphicState::GetSMaskGraphicState( mask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode)); SkMatrix identity; @@ -1941,7 +1940,7 @@ void SkPDFDevice::populateGraphicStateEntryFromPaint( } } -int SkPDFDevice::addGraphicStateResource(SkPDFGraphicState* gs) { +int SkPDFDevice::addGraphicStateResource(SkPDFObject* gs) { // Assumes that gs has been canonicalized (so we can directly compare // pointers). int result = fGraphicStateResources.find(gs); diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h index 51dd643faa..fd870fe97f 100644 --- a/src/pdf/SkPDFDevice.h +++ b/src/pdf/SkPDFDevice.h @@ -203,7 +203,7 @@ private: SkPDFArray* fAnnotations; SkTDArray<NamedDestination*> fNamedDestinations; - SkTDArray<SkPDFGraphicState*> fGraphicStateResources; + SkTDArray<SkPDFObject*> fGraphicStateResources; SkTDArray<SkPDFObject*> fXObjectResources; SkTDArray<SkPDFFont*> fFontResources; SkTDArray<SkPDFObject*> fShaderResources; @@ -271,7 +271,7 @@ private: const SkPaint& paint, bool hasText, GraphicStateEntry* entry); - int addGraphicStateResource(SkPDFGraphicState* gs); + int addGraphicStateResource(SkPDFObject* gs); int addXObjectResource(SkPDFObject* xObject); void updateFont(const SkPaint& paint, uint16_t glyphID, diff --git a/src/pdf/SkPDFGraphicState.cpp b/src/pdf/SkPDFGraphicState.cpp index 6922b08e9e..04eda5812a 100644 --- a/src/pdf/SkPDFGraphicState.cpp +++ b/src/pdf/SkPDFGraphicState.cpp @@ -70,66 +70,58 @@ static const char* as_blend_mode(SkXfermode::Mode mode) { return NULL; } -static bool equivalent(const SkPaint& a, const SkPaint& b) { - // We're only interested in some fields of the SkPaint, so we have - // a custom equality function. - if (SkColorGetA(a.getColor()) != SkColorGetA(b.getColor()) || - a.getStrokeCap() != b.getStrokeCap() || - a.getStrokeJoin() != b.getStrokeJoin() || - a.getStrokeWidth() != b.getStrokeWidth() || - a.getStrokeMiter() != b.getStrokeMiter()) { - return false; +// If a SkXfermode is unsupported in PDF, this function returns +// SrcOver, otherwise, it returns that Xfermode as a Mode. +static SkXfermode::Mode mode_for_pdf(const SkXfermode* xfermode) { + SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode; + if (xfermode) { + xfermode->asMode(&mode); } - - SkXfermode::Mode aXfermodeName = SkXfermode::kSrcOver_Mode; - SkXfermode* aXfermode = a.getXfermode(); - if (aXfermode) { - aXfermode->asMode(&aXfermodeName); - } - if (aXfermodeName < 0 || aXfermodeName > SkXfermode::kLastMode || - as_blend_mode(aXfermodeName) == NULL) { - aXfermodeName = SkXfermode::kSrcOver_Mode; - } - const char* aXfermodeString = as_blend_mode(aXfermodeName); - SkASSERT(aXfermodeString != NULL); - - SkXfermode::Mode bXfermodeName = SkXfermode::kSrcOver_Mode; - SkXfermode* bXfermode = b.getXfermode(); - if (bXfermode) { - bXfermode->asMode(&bXfermodeName); - } - if (bXfermodeName < 0 || bXfermodeName > SkXfermode::kLastMode || - as_blend_mode(bXfermodeName) == NULL) { - bXfermodeName = SkXfermode::kSrcOver_Mode; + switch (mode) { + case SkXfermode::kSrcOver_Mode: + case SkXfermode::kMultiply_Mode: + case SkXfermode::kScreen_Mode: + case SkXfermode::kOverlay_Mode: + case SkXfermode::kDarken_Mode: + case SkXfermode::kLighten_Mode: + case SkXfermode::kColorDodge_Mode: + case SkXfermode::kColorBurn_Mode: + case SkXfermode::kHardLight_Mode: + case SkXfermode::kSoftLight_Mode: + case SkXfermode::kDifference_Mode: + case SkXfermode::kExclusion_Mode: + case SkXfermode::kHue_Mode: + case SkXfermode::kSaturation_Mode: + case SkXfermode::kColor_Mode: + case SkXfermode::kLuminosity_Mode: + // Mode is suppported and handled by pdf graphics state. + return mode; + default: + return SkXfermode::kSrcOver_Mode; // Default mode. } - const char* bXfermodeString = as_blend_mode(bXfermodeName); - SkASSERT(bXfermodeString != NULL); - - return strcmp(aXfermodeString, bXfermodeString) == 0; -} - -bool SkPDFGraphicState::equals(const SkPaint& paint) const { - return equivalent(paint, fPaint); } -SkPDFGraphicState::~SkPDFGraphicState() {} - -void SkPDFGraphicState::emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) { - populateDict(); - SkPDFDict::emitObject(stream, objNumMap, substitutes); -} +SkPDFGraphicState::SkPDFGraphicState(const SkPaint& p) + : fStrokeWidth(p.getStrokeWidth()) + , fStrokeMiter(p.getStrokeMiter()) + , fAlpha(p.getAlpha()) + , fStrokeCap(SkToU8(p.getStrokeCap())) + , fStrokeJoin(SkToU8(p.getStrokeJoin())) + , fMode(SkToU8(mode_for_pdf(p.getXfermode()))) {} // static SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint( SkPDFCanon* canon, const SkPaint& paint) { SkASSERT(canon); - SkPDFGraphicState* pdfGraphicState = canon->findGraphicState(paint); - if (pdfGraphicState) { - return SkRef(pdfGraphicState); + SkPDFGraphicState key(paint); + if (const SkPDFGraphicState* canonGS = canon->findGraphicState(key)) { + // The returned SkPDFGraphicState must be made non-const, + // since the emitObject() interface is non-const. But We + // promise that there is no way to mutate this object from + // here on out. + return SkRef(const_cast<SkPDFGraphicState*>(canonGS)); } - pdfGraphicState = new SkPDFGraphicState(paint); + SkPDFGraphicState* pdfGraphicState = new SkPDFGraphicState(paint); canon->addGraphicState(pdfGraphicState); return pdfGraphicState; } @@ -159,12 +151,15 @@ SkPDFObject* create_invert_function() { template <typename T> void unref(T* ptr) { ptr->unref(); } } // namespace -SK_DECLARE_STATIC_LAZY_PTR(SkPDFObject, invertFunction, - create_invert_function, unref<SkPDFObject>); +SK_DECLARE_STATIC_LAZY_PTR(SkPDFObject, + invertFunction, + create_invert_function, + unref<SkPDFObject>); // static -SkPDFGraphicState* SkPDFGraphicState::GetSMaskGraphicState( - SkPDFFormXObject* sMask, bool invert, SkPDFSMaskMode sMaskMode) { +SkPDFDict* SkPDFGraphicState::GetSMaskGraphicState(SkPDFFormXObject* sMask, + bool invert, + SkPDFSMaskMode sMaskMode) { // The practical chances of using the same mask more than once are unlikely // enough that it's not worth canonicalizing. SkAutoTUnref<SkPDFDict> sMaskDict(new SkPDFDict("Mask")); @@ -174,81 +169,64 @@ SkPDFGraphicState* SkPDFGraphicState::GetSMaskGraphicState( sMaskDict->insertName("S", "Luminosity"); } sMaskDict->insert("G", new SkPDFObjRef(sMask))->unref(); - - SkPDFGraphicState* result = new SkPDFGraphicState; - result->fPopulated = true; - result->insertName("Type", "ExtGState"); - result->insert("SMask", sMaskDict.get()); - if (invert) { sMaskDict->insert("TR", new SkPDFObjRef(invertFunction.get()))->unref(); } + SkPDFDict* result = new SkPDFDict("ExtGState"); + result->insert("SMask", sMaskDict.get()); return result; } -SkPDFGraphicState* SkPDFGraphicState::CreateNoSMaskGraphicState() { - SkPDFGraphicState* noSMaskGS = SkNEW(SkPDFGraphicState); - noSMaskGS->fPopulated = true; - noSMaskGS->insertName("Type", "ExtGState"); +namespace { +SkPDFDict* create_no_smask_graphic_state() { + SkPDFDict* noSMaskGS = new SkPDFDict("ExtGState"); noSMaskGS->insertName("SMask", "None"); return noSMaskGS; } - -SK_DECLARE_STATIC_LAZY_PTR( - SkPDFGraphicState, noSMaskGraphicState, - SkPDFGraphicState::CreateNoSMaskGraphicState, unref<SkPDFGraphicState>); +} // namespace +SK_DECLARE_STATIC_LAZY_PTR(SkPDFDict, + noSMaskGraphicState, + create_no_smask_graphic_state, + unref<SkPDFDict>); // static -SkPDFGraphicState* SkPDFGraphicState::GetNoSMaskGraphicState() { +SkPDFDict* SkPDFGraphicState::GetNoSMaskGraphicState() { return SkRef(noSMaskGraphicState.get()); } -SkPDFGraphicState::SkPDFGraphicState() - : fPopulated(false) {} - -SkPDFGraphicState::SkPDFGraphicState(const SkPaint& paint) - : fPaint(paint), fPopulated(false) {} - -// populateDict and operator== have to stay in sync with each other. -void SkPDFGraphicState::populateDict() { - if (!fPopulated) { - fPopulated = true; - insertName("Type", "ExtGState"); - - SkAutoTUnref<SkPDFScalar> alpha( - new SkPDFScalar(SkScalarDiv(fPaint.getAlpha(), 0xFF))); - insert("CA", alpha.get()); - insert("ca", alpha.get()); - - SK_COMPILE_ASSERT(SkPaint::kButt_Cap == 0, paint_cap_mismatch); - SK_COMPILE_ASSERT(SkPaint::kRound_Cap == 1, paint_cap_mismatch); - SK_COMPILE_ASSERT(SkPaint::kSquare_Cap == 2, paint_cap_mismatch); - SK_COMPILE_ASSERT(SkPaint::kCapCount == 3, paint_cap_mismatch); - SkASSERT(fPaint.getStrokeCap() >= 0 && fPaint.getStrokeCap() <= 2); - insertInt("LC", fPaint.getStrokeCap()); - - SK_COMPILE_ASSERT(SkPaint::kMiter_Join == 0, paint_join_mismatch); - SK_COMPILE_ASSERT(SkPaint::kRound_Join == 1, paint_join_mismatch); - SK_COMPILE_ASSERT(SkPaint::kBevel_Join == 2, paint_join_mismatch); - SK_COMPILE_ASSERT(SkPaint::kJoinCount == 3, paint_join_mismatch); - SkASSERT(fPaint.getStrokeJoin() >= 0 && fPaint.getStrokeJoin() <= 2); - insertInt("LJ", fPaint.getStrokeJoin()); - - insertScalar("LW", fPaint.getStrokeWidth()); - insertScalar("ML", fPaint.getStrokeMiter()); - insert("SA", new SkPDFBool(true))->unref(); // Auto stroke adjustment. - - SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode; - // If asMode fails, default to kSrcOver_Mode. - if (fPaint.getXfermode()) - fPaint.getXfermode()->asMode(&xfermode); - // If we don't support the mode, just use kSrcOver_Mode. - if (xfermode < 0 || xfermode > SkXfermode::kLastMode || - as_blend_mode(xfermode) == NULL) { - xfermode = SkXfermode::kSrcOver_Mode; - NOT_IMPLEMENTED("unsupported xfermode", false); - } - insertName("BM", as_blend_mode(xfermode)); - } +void SkPDFGraphicState::emitObject(SkWStream* stream, + const SkPDFObjNumMap& objNumMap, + const SkPDFSubstituteMap& substitutes) { + SkAutoTUnref<SkPDFDict> dict(SkNEW_ARGS(SkPDFDict, ("ExtGState"))); + dict->insertName("Type", "ExtGState"); + + SkAutoTUnref<SkPDFScalar> alpha(new SkPDFScalar(SkScalarDiv(fAlpha, 0xFF))); + dict->insert("CA", alpha.get()); + dict->insert("ca", alpha.get()); + + SkPaint::Cap strokeCap = (SkPaint::Cap)fStrokeCap; + SkPaint::Join strokeJoin = (SkPaint::Join)fStrokeJoin; + SkXfermode::Mode xferMode = (SkXfermode::Mode)fMode; + + SK_COMPILE_ASSERT(SkPaint::kButt_Cap == 0, paint_cap_mismatch); + SK_COMPILE_ASSERT(SkPaint::kRound_Cap == 1, paint_cap_mismatch); + SK_COMPILE_ASSERT(SkPaint::kSquare_Cap == 2, paint_cap_mismatch); + SK_COMPILE_ASSERT(SkPaint::kCapCount == 3, paint_cap_mismatch); + SkASSERT(strokeCap >= 0 && strokeCap <= 2); + dict->insertInt("LC", strokeCap); + + SK_COMPILE_ASSERT(SkPaint::kMiter_Join == 0, paint_join_mismatch); + SK_COMPILE_ASSERT(SkPaint::kRound_Join == 1, paint_join_mismatch); + SK_COMPILE_ASSERT(SkPaint::kBevel_Join == 2, paint_join_mismatch); + SK_COMPILE_ASSERT(SkPaint::kJoinCount == 3, paint_join_mismatch); + SkASSERT(strokeJoin >= 0 && strokeJoin <= 2); + dict->insertInt("LJ", strokeJoin); + + dict->insertScalar("LW", fStrokeWidth); + dict->insertScalar("ML", fStrokeMiter); + // SA = Auto stroke adjustment. + dict->insert("SA", new SkPDFBool(true))->unref(); + dict->insertName("BM", as_blend_mode(xferMode)); + dict->emitObject(stream, objNumMap, substitutes); } diff --git a/src/pdf/SkPDFGraphicState.h b/src/pdf/SkPDFGraphicState.h index 85a324b191..dddf439db3 100644 --- a/src/pdf/SkPDFGraphicState.h +++ b/src/pdf/SkPDFGraphicState.h @@ -13,19 +13,17 @@ #include "SkPaint.h" #include "SkPDFTypes.h" #include "SkTemplates.h" +#include "SkChecksum.h" +class SkPDFCanon; class SkPDFFormXObject; /** \class SkPDFGraphicState SkPaint objects roughly correspond to graphic state dictionaries that can be installed. So that a given dictionary is only output to the pdf file - once, we want to canonicalize them. Static methods in this class manage - a weakly referenced set of SkPDFGraphicState objects: when the last - reference to a SkPDFGraphicState is removed, it removes itself from the - static set of objects. - + once, we want to canonicalize them. */ -class SkPDFGraphicState : public SkPDFDict { +class SkPDFGraphicState : public SkPDFObject { SK_DECLARE_INST_COUNT(SkPDFGraphicState) public: enum SkPDFSMaskMode { @@ -33,8 +31,6 @@ public: kLuminosity_SMaskMode }; - virtual ~SkPDFGraphicState(); - // Override emitObject so that we can populate the dictionary on // demand. virtual void emitObject(SkWStream* stream, @@ -57,32 +53,37 @@ public: * @param sMask The form xobject to use as a soft mask. * @param invert Indicates if the alpha of the sMask should be inverted. * @param sMaskMode Whether to use alpha or luminosity for the sMask. + * + * These are not de-duped. */ - static SkPDFGraphicState* GetSMaskGraphicState(SkPDFFormXObject* sMask, - bool invert, - SkPDFSMaskMode sMaskMode); + static SkPDFDict* GetSMaskGraphicState(SkPDFFormXObject* sMask, + bool invert, + SkPDFSMaskMode sMaskMode); /** Get a graphic state that only unsets the soft mask. The reference * count of the object is incremented and it is the caller's responsibility * to unreference it when done. This is needed to accommodate the weak * reference pattern used when the returned object is new and has no * other references. + * + * The returned object is a singleton. */ - static SkPDFGraphicState* GetNoSMaskGraphicState(); - - bool equals(const SkPaint&) const; + static SkPDFDict* GetNoSMaskGraphicState(); - // Only public for SK_DECLARE_STATIC_LAZY_PTR - static SkPDFGraphicState* CreateNoSMaskGraphicState(); + bool operator==(const SkPDFGraphicState& rhs) const { + return 0 == memcmp(&fStrokeWidth, &rhs.fStrokeWidth, 12); + } + uint32_t hash() const { return SkChecksum::Murmur3(&fStrokeWidth, 12); } private: - const SkPaint fPaint; - bool fPopulated; - - SkPDFGraphicState(); - SkPDFGraphicState(const SkPaint& paint); - - void populateDict(); + const SkScalar fStrokeWidth; + const SkScalar fStrokeMiter; + const uint8_t fAlpha; + const uint8_t fStrokeCap; // SkPaint::Cap + const uint8_t fStrokeJoin; // SkPaint::Join + const uint8_t fMode; // SkXfermode::Mode + + SkPDFGraphicState(const SkPaint&); typedef SkPDFDict INHERITED; }; diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp index 303212596d..596bbc7d2c 100644 --- a/src/pdf/SkPDFShader.cpp +++ b/src/pdf/SkPDFShader.cpp @@ -635,7 +635,7 @@ static SkStream* create_pattern_fill_content(int gsIndex, SkRect& bounds) { * Creates a ExtGState with the SMask set to the luminosityShader in * luminosity mode. The shader pattern extends to the bbox. */ -static SkPDFGraphicState* create_smask_graphic_state( +static SkPDFObject* create_smask_graphic_state( SkPDFCanon* canon, SkScalar dpi, const SkPDFShader::State& state) { SkRect bbox; bbox.set(state.fBBox); @@ -676,7 +676,7 @@ SkPDFAlphaFunctionShader* SkPDFAlphaFunctionShader::Create( // Create resource dict with alpha graphics state as G0 and // pattern shader as P0, then write content stream. - SkAutoTUnref<SkPDFGraphicState> alphaGs( + SkAutoTUnref<SkPDFObject> alphaGs( create_smask_graphic_state(canon, dpi, state)); SkPDFAlphaFunctionShader* alphaFunctionShader = |