Index: src/pdf/SkPDFGraphicState.cpp |
diff --git a/src/pdf/SkPDFGraphicState.cpp b/src/pdf/SkPDFGraphicState.cpp |
index 6922b08e9efcb3e3b12a37da0177f45aec76628d..04eda5812ad16f7e9981d8266e78a24b519d8674 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); |
} |