| Index: src/core/SkXfermode.cpp
|
| diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
|
| index 2aaef70fb97c809296dd70fcca264fe4eac8151d..92743c2fddeddd86d62dc9df14f358c5ee22cdc4 100644
|
| --- a/src/core/SkXfermode.cpp
|
| +++ b/src/core/SkXfermode.cpp
|
| @@ -1194,7 +1194,11 @@ static Sk4f ramp(const Sk4f& v0, const Sk4f& v1, const Sk4f& t) {
|
| }
|
|
|
| static Sk4f clamp_255(const Sk4f& value) {
|
| - return Sk4f::Min(value, Sk4f(255));
|
| + return Sk4f::Min(Sk4f(255), value);
|
| +}
|
| +
|
| +static Sk4f clamp_0_255(const Sk4f& value) {
|
| + return Sk4f::Max(Sk4f(0), Sk4f::Min(Sk4f(255), value));
|
| }
|
|
|
| /**
|
| @@ -1286,12 +1290,27 @@ struct Screen4f {
|
| const Sk4f inv255(gInv255);
|
| Sk4f s4 = src;
|
| Sk4f d4 = dst;
|
| - return check_as_pmfloat(check_as_pmfloat(s4 + d4 - s4 * d4 * inv255));
|
| + return check_as_pmfloat(s4 + d4 - s4 * d4 * inv255);
|
| }
|
| static const bool kFoldCoverageIntoSrcAlpha = true;
|
| static const SkXfermode::Mode kMode = SkXfermode::kScreen_Mode;
|
| };
|
|
|
| +struct Multiply4f {
|
| + static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
|
| + const Sk4f inv255(gInv255);
|
| + Sk4f sa = Sk4f(src.a());
|
| + Sk4f da = Sk4f(dst.a());
|
| + Sk4f sc = src;
|
| + Sk4f dc = dst;
|
| + Sk4f rc = sc + dc + (sc * (dc - da) - dc * sa) * inv255;
|
| + // ra = srcover(sa, da), but the calc for rc happens to accomplish this for us
|
| + return check_as_pmfloat(clamp_0_255(rc));
|
| + }
|
| + static const bool kFoldCoverageIntoSrcAlpha = false;
|
| + static const SkXfermode::Mode kMode = SkXfermode::kMultiply_Mode;
|
| +};
|
| +
|
| template <typename ProcType>
|
| class SkT4fXfermode : public SkProcCoeffXfermode {
|
| public:
|
| @@ -1423,6 +1442,9 @@ SkXfermode* create_mode(int iMode) {
|
| case SkXfermode::kScreen_Mode:
|
| xfer = SkT4fXfermode<Screen4f>::Create(rec);
|
| break;
|
| + case SkXfermode::kMultiply_Mode:
|
| + xfer = SkT4fXfermode<Multiply4f>::Create(rec);
|
| + break;
|
| default:
|
| break;
|
| }
|
|
|