| 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);
|
| }
|
|
|