aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar halcanary <halcanary@google.com>2015-04-01 13:31:19 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-04-01 13:31:19 -0700
commitbe27a118c277af23377d38e9b3bfd3fcc276114f (patch)
tree1898203654addbbb8cf77f1b3231d50c1860ead3
parent03e5161bed3bdfa0d9fb0867378237bac7d8bd12 (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.h6
-rw-r--r--src/pdf/SkPDFCanon.cpp16
-rw-r--r--src/pdf/SkPDFCanon.h22
-rw-r--r--src/pdf/SkPDFDevice.cpp5
-rw-r--r--src/pdf/SkPDFDevice.h4
-rw-r--r--src/pdf/SkPDFGraphicState.cpp210
-rw-r--r--src/pdf/SkPDFGraphicState.h47
-rw-r--r--src/pdf/SkPDFShader.cpp4
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 =