| Index: skia/sgl/SkXfermode.cpp
|
| ===================================================================
|
| --- skia/sgl/SkXfermode.cpp (revision 16859)
|
| +++ skia/sgl/SkXfermode.cpp (working copy)
|
| @@ -1,997 +0,0 @@
|
| -/*
|
| - * Copyright (C) 2006 The Android Open Source Project
|
| - *
|
| - * Licensed under the Apache License, Version 2.0 (the "License");
|
| - * you may not use this file except in compliance with the License.
|
| - * You may obtain a copy of the License at
|
| - *
|
| - * http://www.apache.org/licenses/LICENSE-2.0
|
| - *
|
| - * Unless required by applicable law or agreed to in writing, software
|
| - * distributed under the License is distributed on an "AS IS" BASIS,
|
| - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| - * See the License for the specific language governing permissions and
|
| - * limitations under the License.
|
| - */
|
| -
|
| -#include "SkXfermode.h"
|
| -#include "SkColorPriv.h"
|
| -
|
| -#define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
|
| -
|
| -static SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst, U8CPU alpha) {
|
| - unsigned scale = SkAlpha255To256(alpha);
|
| -
|
| - unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale);
|
| - unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale);
|
| - unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale);
|
| - unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale);
|
| -
|
| - return SkPackARGB32(a, r, g, b);
|
| -}
|
| -
|
| -// idea for higher precision blends in xfer procs (and slightly faster)
|
| -// see DstATop as a probable caller
|
| -static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
|
| - SkASSERT(a <= 255);
|
| - SkASSERT(b <= 255);
|
| - SkASSERT(c <= 255);
|
| - SkASSERT(d <= 255);
|
| - unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
|
| - unsigned result = (prod + (prod >> 8)) >> 8;
|
| - SkASSERT(result <= 255);
|
| - return result;
|
| -}
|
| -
|
| -static unsigned saturated_add(unsigned a, unsigned b) {
|
| - SkASSERT(a <= 255);
|
| - SkASSERT(b <= 255);
|
| - unsigned sum = a + b;
|
| - if (sum > 255) {
|
| - sum = 255;
|
| - }
|
| - return sum;
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) {
|
| - return false;
|
| -}
|
| -
|
| -SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) {
|
| - // no-op. subclasses should override this
|
| - return dst;
|
| -}
|
| -
|
| -void SkXfermode::xfer32(SK_RESTRICT SkPMColor dst[],
|
| - const SK_RESTRICT SkPMColor src[], int count,
|
| - const SK_RESTRICT SkAlpha aa[]) {
|
| - SkASSERT(dst && src && count >= 0);
|
| -
|
| - if (NULL == aa) {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - dst[i] = this->xferColor(src[i], dst[i]);
|
| - }
|
| - } else {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - unsigned a = aa[i];
|
| - if (0 != a) {
|
| - SkPMColor dstC = dst[i];
|
| - SkPMColor C = this->xferColor(src[i], dstC);
|
| - if (0xFF != a) {
|
| - C = SkFourByteInterp(C, dstC, a);
|
| - }
|
| - dst[i] = C;
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void SkXfermode::xfer16(SK_RESTRICT uint16_t dst[],
|
| - const SK_RESTRICT SkPMColor src[], int count,
|
| - const SK_RESTRICT SkAlpha aa[]) {
|
| - SkASSERT(dst && src && count >= 0);
|
| -
|
| - if (NULL == aa) {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
|
| - dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
|
| - }
|
| - } else {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - unsigned a = aa[i];
|
| - if (0 != a) {
|
| - SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
|
| - SkPMColor C = this->xferColor(src[i], dstC);
|
| - if (0xFF != a) {
|
| - C = SkFourByteInterp(C, dstC, a);
|
| - }
|
| - dst[i] = SkPixel32ToPixel16_ToU16(C);
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void SkXfermode::xfer4444(SK_RESTRICT SkPMColor16 dst[],
|
| - const SK_RESTRICT SkPMColor src[], int count,
|
| - const SK_RESTRICT SkAlpha aa[])
|
| -{
|
| - SkASSERT(dst && src && count >= 0);
|
| -
|
| - if (NULL == aa) {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
|
| - dst[i] = SkPixel32ToPixel4444(this->xferColor(src[i], dstC));
|
| - }
|
| - } else {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - unsigned a = aa[i];
|
| - if (0 != a) {
|
| - SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
|
| - SkPMColor C = this->xferColor(src[i], dstC);
|
| - if (0xFF != a) {
|
| - C = SkFourByteInterp(C, dstC, a);
|
| - }
|
| - dst[i] = SkPixel32ToPixel4444(C);
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void SkXfermode::xferA8(SK_RESTRICT SkAlpha dst[],
|
| - const SkPMColor src[], int count,
|
| - const SK_RESTRICT SkAlpha aa[])
|
| -{
|
| - SkASSERT(dst && src && count >= 0);
|
| -
|
| - if (NULL == aa) {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
|
| - dst[i] = SkToU8(SkGetPackedA32(res));
|
| - }
|
| - } else {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - unsigned a = aa[i];
|
| - if (0 != a) {
|
| - SkAlpha dstA = dst[i];
|
| - unsigned A = SkGetPackedA32(this->xferColor(src[i],
|
| - (SkPMColor)(dstA << SK_A32_SHIFT)));
|
| - if (0xFF != a) {
|
| - A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
|
| - }
|
| - dst[i] = SkToU8(A);
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -void SkProcXfermode::xfer32(SK_RESTRICT SkPMColor dst[],
|
| - const SK_RESTRICT SkPMColor src[], int count,
|
| - const SK_RESTRICT SkAlpha aa[]) {
|
| - SkASSERT(dst && src && count >= 0);
|
| -
|
| - SkXfermodeProc proc = fProc;
|
| -
|
| - if (NULL != proc) {
|
| - if (NULL == aa) {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - dst[i] = proc(src[i], dst[i]);
|
| - }
|
| - } else {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - unsigned a = aa[i];
|
| - if (0 != a) {
|
| - SkPMColor dstC = dst[i];
|
| - SkPMColor C = proc(src[i], dstC);
|
| - if (a != 0xFF) {
|
| - C = SkFourByteInterp(C, dstC, a);
|
| - }
|
| - dst[i] = C;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void SkProcXfermode::xfer16(SK_RESTRICT uint16_t dst[],
|
| - const SK_RESTRICT SkPMColor src[], int count,
|
| - const SK_RESTRICT SkAlpha aa[]) {
|
| - SkASSERT(dst && src && count >= 0);
|
| -
|
| - SkXfermodeProc proc = fProc;
|
| -
|
| - if (NULL != proc) {
|
| - if (NULL == aa) {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
|
| - dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
|
| - }
|
| - } else {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - unsigned a = aa[i];
|
| - if (0 != a) {
|
| - SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
|
| - SkPMColor C = proc(src[i], dstC);
|
| - if (0xFF != a) {
|
| - C = SkFourByteInterp(C, dstC, a);
|
| - }
|
| - dst[i] = SkPixel32ToPixel16_ToU16(C);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void SkProcXfermode::xfer4444(SK_RESTRICT SkPMColor16 dst[],
|
| - const SK_RESTRICT SkPMColor src[], int count,
|
| - const SK_RESTRICT SkAlpha aa[]) {
|
| - SkASSERT(dst && src && count >= 0);
|
| -
|
| - SkXfermodeProc proc = fProc;
|
| -
|
| - if (NULL != proc) {
|
| - if (NULL == aa) {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
|
| - dst[i] = SkPixel32ToPixel4444(proc(src[i], dstC));
|
| - }
|
| - } else {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - unsigned a = aa[i];
|
| - if (0 != a) {
|
| - SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
|
| - SkPMColor C = proc(src[i], dstC);
|
| - if (0xFF != a) {
|
| - C = SkFourByteInterp(C, dstC, a);
|
| - }
|
| - dst[i] = SkPixel32ToPixel4444(C);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -void SkProcXfermode::xferA8(SK_RESTRICT SkAlpha dst[],
|
| - const SK_RESTRICT SkPMColor src[], int count,
|
| - const SK_RESTRICT SkAlpha aa[]) {
|
| - SkASSERT(dst && src && count >= 0);
|
| -
|
| - SkXfermodeProc proc = fProc;
|
| -
|
| - if (NULL != proc) {
|
| - if (NULL == aa) {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
|
| - dst[i] = SkToU8(SkGetPackedA32(res));
|
| - }
|
| - } else {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - unsigned a = aa[i];
|
| - if (0 != a) {
|
| - SkAlpha dstA = dst[i];
|
| - SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
|
| - unsigned A = SkGetPackedA32(res);
|
| - if (0xFF != a) {
|
| - A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
|
| - }
|
| - dst[i] = SkToU8(A);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -
|
| -SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
|
| - : SkXfermode(buffer) {
|
| - fProc = (SkXfermodeProc)buffer.readFunctionPtr();
|
| -}
|
| -
|
| -void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) {
|
| - buffer.writeFunctionPtr((void*)fProc);
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -class SkProcCoeffXfermode : public SkProcXfermode {
|
| -public:
|
| - SkProcCoeffXfermode(SkXfermodeProc proc, Coeff sc, Coeff dc)
|
| - : INHERITED(proc), fSrcCoeff(sc), fDstCoeff(dc) {
|
| - }
|
| -
|
| - virtual bool asCoeff(Coeff* sc, Coeff* dc) {
|
| - if (sc) {
|
| - *sc = fSrcCoeff;
|
| - }
|
| - if (dc) {
|
| - *dc = fDstCoeff;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - virtual Factory getFactory() { return CreateProc; }
|
| - virtual void flatten(SkFlattenableWriteBuffer& buffer) {
|
| - this->INHERITED::flatten(buffer);
|
| - buffer.write32(fSrcCoeff);
|
| - buffer.write32(fDstCoeff);
|
| - }
|
| -
|
| -protected:
|
| - SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer)
|
| - : INHERITED(buffer) {
|
| - fSrcCoeff = (Coeff)buffer.readU32();
|
| - fDstCoeff = (Coeff)buffer.readU32();
|
| - }
|
| -
|
| -private:
|
| - Coeff fSrcCoeff, fDstCoeff;
|
| -
|
| - static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
|
| - return SkNEW_ARGS(SkProcCoeffXfermode, (buffer)); }
|
| -
|
| - typedef SkProcXfermode INHERITED;
|
| -};
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -// kClear_Mode, //!< [0, 0]
|
| -static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
|
| - return 0;
|
| -}
|
| -
|
| -// kSrc_Mode, //!< [Sa, Sc]
|
| -static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
|
| - return src;
|
| -}
|
| -
|
| -// kDst_Mode, //!< [Da, Dc]
|
| -static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
|
| - return dst;
|
| -}
|
| -
|
| -// kSrcOver_Mode, //!< [Sa + (1 - Sa)*Da, Sc + (1 - Sa)*Dc]
|
| -static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
|
| - return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
|
| -}
|
| -
|
| -// kDstOver_Mode, //!< [Sa + (1 - Sa)*Da, Dc + (1 - Da)*Sc]
|
| -static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
|
| - unsigned sa = SkGetPackedA32(src);
|
| - unsigned da = SkGetPackedA32(dst);
|
| - unsigned ida = 255 - da;
|
| -
|
| - return SkPackARGB32(sa + da - SkAlphaMulAlpha(sa, da),
|
| - SkGetPackedR32(dst) + SkAlphaMulAlpha(ida, SkGetPackedR32(src)),
|
| - SkGetPackedG32(dst) + SkAlphaMulAlpha(ida, SkGetPackedG32(src)),
|
| - SkGetPackedB32(dst) + SkAlphaMulAlpha(ida, SkGetPackedB32(src)));
|
| -}
|
| -
|
| -// kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
|
| -static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
|
| - return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
|
| -}
|
| -
|
| -// kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
|
| -static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
|
| - return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
|
| -}
|
| -
|
| -// kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
|
| -static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
|
| - return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
|
| -}
|
| -
|
| -// kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
|
| -static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
|
| - return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
|
| -}
|
| -
|
| -// kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
|
| -static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
|
| - unsigned sa = SkGetPackedA32(src);
|
| - unsigned da = SkGetPackedA32(dst);
|
| - unsigned isa = 255 - sa;
|
| -
|
| - return SkPackARGB32(da,
|
| - SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
|
| - SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
|
| - SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
|
| - SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
|
| - SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
|
| - SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
|
| -}
|
| -
|
| -// kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
|
| -static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
|
| - unsigned sa = SkGetPackedA32(src);
|
| - unsigned da = SkGetPackedA32(dst);
|
| - unsigned ida = 255 - da;
|
| -
|
| - return SkPackARGB32(sa,
|
| - SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
|
| - SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
|
| - SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
|
| - SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
|
| - SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
|
| - SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
|
| -}
|
| -
|
| -// kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
|
| -static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
|
| - unsigned sa = SkGetPackedA32(src);
|
| - unsigned da = SkGetPackedA32(dst);
|
| - unsigned isa = 255 - sa;
|
| - unsigned ida = 255 - da;
|
| -
|
| - return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
|
| - SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
|
| - SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
|
| - SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
|
| - SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
|
| - SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
|
| - SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
|
| -}
|
| -
|
| -
|
| -// kDarken_Mode, [Sa + Da - Sa·Da, Sc·(1 - Da) + Dc·(1 - Sa) + min(Sc, Dc)]
|
| -
|
| -static inline unsigned darken_p(unsigned src, unsigned dst,
|
| - unsigned src_mul, unsigned dst_mul) {
|
| - return ((dst_mul * src + src_mul * dst) >> 8) + SkMin32(src, dst);
|
| -}
|
| -
|
| -static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
|
| - unsigned sa = SkGetPackedA32(src);
|
| - unsigned da = SkGetPackedA32(dst);
|
| - unsigned src_scale = SkAlpha255To256(255 - sa);
|
| - unsigned dst_scale = SkAlpha255To256(255 - da);
|
| -
|
| - unsigned ra = sa + da - SkAlphaMulAlpha(sa, da);
|
| - unsigned rr = darken_p(SkGetPackedR32(src), SkGetPackedR32(dst),
|
| - src_scale, dst_scale);
|
| - unsigned rg = darken_p(SkGetPackedG32(src), SkGetPackedG32(dst),
|
| - src_scale, dst_scale);
|
| - unsigned rb = darken_p(SkGetPackedB32(src), SkGetPackedB32(dst),
|
| - src_scale, dst_scale);
|
| -
|
| - return SkPackARGB32(ra, SkFastMin32(rr, ra),
|
| - SkFastMin32(rg, ra), SkFastMin32(rb, ra));
|
| -}
|
| -
|
| -// kLighten_Mode, [Sa + Da - Sa·Da, Sc·(1 - Da) + Dc·(1 - Sa) + max(Sc, Dc)]
|
| -static inline unsigned lighten_p(unsigned src, unsigned dst,
|
| - unsigned src_mul, unsigned dst_mul) {
|
| - return ((dst_mul * src + src_mul * dst) >> 8) + SkMax32(src, dst);
|
| -}
|
| -
|
| -static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
|
| - unsigned sa = SkGetPackedA32(src);
|
| - unsigned da = SkGetPackedA32(dst);
|
| - unsigned src_scale = SkAlpha255To256(255 - sa);
|
| - unsigned dst_scale = SkAlpha255To256(255 - da);
|
| -
|
| - unsigned ra = sa + da - SkAlphaMulAlpha(sa, da);
|
| - unsigned rr = lighten_p(SkGetPackedR32(src), SkGetPackedR32(dst),
|
| - src_scale, dst_scale);
|
| - unsigned rg = lighten_p(SkGetPackedG32(src), SkGetPackedG32(dst),
|
| - src_scale, dst_scale);
|
| - unsigned rb = lighten_p(SkGetPackedB32(src), SkGetPackedB32(dst),
|
| - src_scale, dst_scale);
|
| -
|
| - return SkPackARGB32(ra, SkFastMin32(rr, ra),
|
| - SkFastMin32(rg, ra), SkFastMin32(rb, ra));
|
| -}
|
| -
|
| -static SkPMColor mult_modeproc(SkPMColor src, SkPMColor dst) {
|
| - int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
|
| - int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
|
| - int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
|
| - int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
|
| - return SkPackARGB32(a, r, g, b);
|
| -}
|
| -
|
| -static inline int screen_byte(int a, int b) {
|
| - return a + b - SkAlphaMulAlpha(a, b);
|
| -}
|
| -
|
| -static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
|
| - int a = screen_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
|
| - int r = screen_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
|
| - int g = screen_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
|
| - int b = screen_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
|
| - return SkPackARGB32(a, r, g, b);
|
| -}
|
| -
|
| -static SkPMColor add_modeproc(SkPMColor src, SkPMColor dst) {
|
| - unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
|
| - unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
|
| - unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
|
| - unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
|
| - return SkPackARGB32(a, r, g, b);
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -class SkClearXfermode : public SkProcCoeffXfermode {
|
| -public:
|
| - SkClearXfermode() : SkProcCoeffXfermode(clear_modeproc,
|
| - kZero_Coeff, kZero_Coeff) {}
|
| -
|
| - virtual void xfer32(SK_RESTRICT SkPMColor dst[],
|
| - const SK_RESTRICT SkPMColor[], int count,
|
| - const SK_RESTRICT SkAlpha aa[]) {
|
| - SkASSERT(dst && count >= 0);
|
| -
|
| - if (NULL == aa) {
|
| - memset(dst, 0, count << 2);
|
| - } else {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - unsigned a = aa[i];
|
| - if (0xFF == a) {
|
| - dst[i] = 0;
|
| - } else if (a != 0) {
|
| - dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
|
| - }
|
| - }
|
| - }
|
| - }
|
| - virtual void xferA8(SK_RESTRICT SkAlpha dst[],
|
| - const SK_RESTRICT SkPMColor[], int count,
|
| - const SK_RESTRICT SkAlpha aa[]) {
|
| - SkASSERT(dst && count >= 0);
|
| -
|
| - if (NULL == aa) {
|
| - memset(dst, 0, count);
|
| - } else {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - unsigned a = aa[i];
|
| - if (0xFF == a) {
|
| - dst[i] = 0;
|
| - } else if (0 != a) {
|
| - dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - virtual Factory getFactory() { return CreateProc; }
|
| -
|
| -private:
|
| - SkClearXfermode(SkFlattenableReadBuffer& buffer)
|
| - : SkProcCoeffXfermode(buffer) {}
|
| -
|
| - static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
|
| - return SkNEW_ARGS(SkClearXfermode, (buffer));
|
| - }
|
| -};
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -class SkSrcXfermode : public SkProcCoeffXfermode {
|
| -public:
|
| - SkSrcXfermode() : SkProcCoeffXfermode(src_modeproc,
|
| - kOne_Coeff, kZero_Coeff) {}
|
| -
|
| - virtual void xfer32(SK_RESTRICT SkPMColor dst[],
|
| - const SK_RESTRICT SkPMColor src[], int count,
|
| - const SK_RESTRICT SkAlpha aa[]) {
|
| - SkASSERT(dst && src && count >= 0);
|
| -
|
| - if (NULL == aa) {
|
| - memcpy(dst, src, count << 2);
|
| - } else {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - unsigned a = aa[i];
|
| - if (a == 0xFF) {
|
| - dst[i] = src[i];
|
| - } else if (a != 0) {
|
| - dst[i] = SkFourByteInterp(src[i], dst[i], a);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - virtual void xferA8(SK_RESTRICT SkAlpha dst[],
|
| - const SK_RESTRICT SkPMColor src[], int count,
|
| - const SK_RESTRICT SkAlpha aa[]) {
|
| - SkASSERT(dst && src && count >= 0);
|
| -
|
| - if (NULL == aa) {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - dst[i] = SkToU8(SkGetPackedA32(src[i]));
|
| - }
|
| - } else {
|
| - for (int i = count - 1; i >= 0; --i) {
|
| - unsigned a = aa[i];
|
| - if (0 != a) {
|
| - unsigned srcA = SkGetPackedA32(src[i]);
|
| - if (a == 0xFF) {
|
| - dst[i] = SkToU8(srcA);
|
| - } else {
|
| - dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - virtual Factory getFactory() { return CreateProc; }
|
| -
|
| -private:
|
| - SkSrcXfermode(SkFlattenableReadBuffer& buffer)
|
| - : SkProcCoeffXfermode(buffer) {}
|
| -
|
| - static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
|
| - return SkNEW_ARGS(SkSrcXfermode, (buffer));
|
| - }
|
| -};
|
| -
|
| -class SkDstInXfermode : public SkProcCoeffXfermode {
|
| -public:
|
| - SkDstInXfermode() : SkProcCoeffXfermode(dstin_modeproc,
|
| - kZero_Coeff, kSA_Coeff) {}
|
| -
|
| - virtual void xfer32(SK_RESTRICT SkPMColor dst[],
|
| - const SK_RESTRICT SkPMColor src[], int count,
|
| - const SK_RESTRICT SkAlpha aa[]) {
|
| - SkASSERT(dst && src);
|
| -
|
| - if (count <= 0) {
|
| - return;
|
| - }
|
| - if (NULL != aa) {
|
| - return this->INHERITED::xfer32(dst, src, count, aa);
|
| - }
|
| -
|
| - do {
|
| - unsigned a = SkGetPackedA32(*src);
|
| - *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
|
| - dst++;
|
| - src++;
|
| - } while (--count != 0);
|
| - }
|
| -
|
| - virtual Factory getFactory() { return CreateProc; }
|
| -
|
| -private:
|
| - SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
|
| -
|
| - static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
|
| - return SkNEW_ARGS(SkDstInXfermode, (buffer));
|
| - }
|
| -
|
| - typedef SkProcCoeffXfermode INHERITED;
|
| -};
|
| -
|
| -class SkDstOutXfermode : public SkProcCoeffXfermode {
|
| -public:
|
| - SkDstOutXfermode() : SkProcCoeffXfermode(dstout_modeproc,
|
| - kZero_Coeff, kISA_Coeff) {}
|
| -
|
| - virtual void xfer32(SK_RESTRICT SkPMColor dst[],
|
| - const SK_RESTRICT SkPMColor src[], int count,
|
| - const SK_RESTRICT SkAlpha aa[]) {
|
| - SkASSERT(dst && src);
|
| -
|
| - if (count <= 0) {
|
| - return;
|
| - }
|
| - if (NULL != aa) {
|
| - return this->INHERITED::xfer32(dst, src, count, aa);
|
| - }
|
| -
|
| - do {
|
| - unsigned a = SkGetPackedA32(*src);
|
| - *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
|
| - dst++;
|
| - src++;
|
| - } while (--count != 0);
|
| - }
|
| -
|
| - virtual Factory getFactory() { return CreateProc; }
|
| -
|
| -private:
|
| - SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
|
| - : INHERITED(buffer) {}
|
| -
|
| - static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
|
| - return SkNEW_ARGS(SkDstOutXfermode, (buffer));
|
| - }
|
| -
|
| - typedef SkProcCoeffXfermode INHERITED;
|
| -};
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -#include "SkPorterDuff.h"
|
| -
|
| -struct ProcCoeff {
|
| - SkXfermodeProc fProc;
|
| - SkXfermode::Coeff fSC;
|
| - SkXfermode::Coeff fDC;
|
| -};
|
| -
|
| -#define CANNOT_USE_COEFF SkXfermode::Coeff(-1)
|
| -
|
| -static const ProcCoeff gProcCoeffs[] = {
|
| - { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff },
|
| - { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff },
|
| - { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff },
|
| - { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff },
|
| - { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff },
|
| - { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff },
|
| - { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff },
|
| - { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff },
|
| - { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff },
|
| - { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff },
|
| - { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff },
|
| - { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff },
|
| - { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
|
| - { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
|
| - { mult_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff },
|
| - { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff },
|
| - { add_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }
|
| -};
|
| -
|
| -SkXfermode* SkPorterDuff::CreateXfermode(SkPorterDuff::Mode mode) {
|
| - SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == SkPorterDuff::kModeCount);
|
| - SkASSERT((unsigned)mode < SkPorterDuff::kModeCount);
|
| -
|
| - switch (mode) {
|
| - case kClear_Mode:
|
| - return SkNEW(SkClearXfermode);
|
| - case kSrc_Mode:
|
| - return SkNEW(SkSrcXfermode);
|
| - case kSrcOver_Mode:
|
| - return NULL;
|
| - case kDstIn_Mode:
|
| - return SkNEW(SkDstInXfermode);
|
| - case kDstOut_Mode:
|
| - return SkNEW(SkDstOutXfermode);
|
| - // these two can't be represented with Coeff
|
| - case kDarken_Mode:
|
| - return SkNEW_ARGS(SkProcXfermode, (darken_modeproc));
|
| - case kLighten_Mode:
|
| - return SkNEW_ARGS(SkProcXfermode, (lighten_modeproc));
|
| - // use the table
|
| - default: {
|
| - const ProcCoeff& rec = gProcCoeffs[mode];
|
| - SkASSERT((unsigned)rec.fSC < SkXfermode::kCoeffCount);
|
| - SkASSERT((unsigned)rec.fDC < SkXfermode::kCoeffCount);
|
| - return SkNEW_ARGS(SkProcCoeffXfermode, (rec.fProc,
|
| - rec.fSC, rec.fDC));
|
| - }
|
| - }
|
| -}
|
| -
|
| -bool SkPorterDuff::IsMode(SkXfermode* xfer, Mode* mode) {
|
| - if (NULL == xfer) {
|
| - if (mode) {
|
| - *mode = kSrcOver_Mode;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - SkXfermode::Coeff sc, dc;
|
| - if (xfer->asCoeff(&sc, &dc)) {
|
| - SkASSERT((unsigned)sc < (unsigned)SkXfermode::kCoeffCount);
|
| - SkASSERT((unsigned)dc < (unsigned)SkXfermode::kCoeffCount);
|
| -
|
| - const ProcCoeff* rec = gProcCoeffs;
|
| - for (size_t i = 0; i < SK_ARRAY_COUNT(gProcCoeffs); i++) {
|
| - if (rec[i].fSC == sc && rec[i].fDC == dc) {
|
| - if (mode) {
|
| - *mode = SkPorterDuff::Mode(i);
|
| - }
|
| - return true;
|
| - }
|
| - }
|
| - }
|
| -
|
| - // no coefficients, or not found in our table
|
| - return false;
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| -#ifdef SK_DEBUG
|
| -static void unit_test() {
|
| - for (unsigned a = 0; a <= 255; a++) {
|
| - for (unsigned c = 0; c <= a; c++) {
|
| - SkPMColor pm = SkPackARGB32(a, c, c, c);
|
| - for (unsigned aa = 0; aa <= 255; aa++) {
|
| - for (unsigned cc = 0; cc <= aa; cc++) {
|
| - SkPMColor pm2 = SkPackARGB32(aa, cc, cc, cc);
|
| -
|
| - const size_t N = SK_ARRAY_COUNT(gProcCoeffs);
|
| - for (size_t i = 0; i < N; i++) {
|
| - gProcCoeffs[i].fProc(pm, pm2);
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| -}
|
| -#endif
|
| -
|
| -SkXfermodeProc SkPorterDuff::GetXfermodeProc(Mode mode) {
|
| -#ifdef SK_DEBUGx
|
| - static bool gUnitTest;
|
| - if (!gUnitTest) {
|
| - gUnitTest = true;
|
| - unit_test();
|
| - }
|
| -#endif
|
| -
|
| - SkXfermodeProc proc = NULL;
|
| -
|
| - if ((unsigned)mode < SkPorterDuff::kModeCount) {
|
| - proc = gProcCoeffs[mode].fProc;
|
| - }
|
| - return proc;
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -//////////// 16bit xfermode procs
|
| -
|
| -#ifdef SK_DEBUG
|
| -static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
|
| -static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
|
| -#endif
|
| -
|
| -static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_255(src));
|
| - return SkPixel32ToPixel16(src);
|
| -}
|
| -
|
| -static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
|
| - return dst;
|
| -}
|
| -
|
| -static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_0(src));
|
| - return dst;
|
| -}
|
| -
|
| -static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_255(src));
|
| - return SkPixel32ToPixel16(src);
|
| -}
|
| -
|
| -static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_0(src));
|
| - return dst;
|
| -}
|
| -
|
| -static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_255(src));
|
| - return dst;
|
| -}
|
| -
|
| -static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_255(src));
|
| - return SkPixel32ToPixel16(src);
|
| -}
|
| -
|
| -static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_255(src));
|
| - return dst;
|
| -}
|
| -
|
| -static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_0(src));
|
| - return dst;
|
| -}
|
| -
|
| -static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
|
| - unsigned isa = 255 - SkGetPackedA32(src);
|
| -
|
| - return SkPackRGB16(
|
| - SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
|
| - SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
|
| - SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
|
| -}
|
| -
|
| -static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_0(src));
|
| - return dst;
|
| -}
|
| -
|
| -static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_255(src));
|
| - return SkPixel32ToPixel16(src);
|
| -}
|
| -
|
| -static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_255(src));
|
| - return dst;
|
| -}
|
| -
|
| -/*********
|
| - darken and lighten boil down to this.
|
| -
|
| - darken = (1 - Sa) * Dc + min(Sc, Dc)
|
| - lighten = (1 - Sa) * Dc + max(Sc, Dc)
|
| -
|
| - if (Sa == 0) these become
|
| - darken = Dc + min(0, Dc) = 0
|
| - lighten = Dc + max(0, Dc) = Dc
|
| -
|
| - if (Sa == 1) these become
|
| - darken = min(Sc, Dc)
|
| - lighten = max(Sc, Dc)
|
| -*/
|
| -
|
| -static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_0(src));
|
| - return 0;
|
| -}
|
| -
|
| -static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_255(src));
|
| - unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
|
| - unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
|
| - unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
|
| - return SkPackRGB16(r, g, b);
|
| -}
|
| -
|
| -static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_0(src));
|
| - return dst;
|
| -}
|
| -
|
| -static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
|
| - SkASSERT(require_255(src));
|
| - unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
|
| - unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
|
| - unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
|
| - return SkPackRGB16(r, g, b);
|
| -}
|
| -
|
| -struct Proc16Rec {
|
| - SkXfermodeProc16 fProc16_0;
|
| - SkXfermodeProc16 fProc16_255;
|
| - SkXfermodeProc16 fProc16_General;
|
| -};
|
| -
|
| -static const Proc16Rec gPorterDuffModeProcs16[] = {
|
| - { NULL, NULL, NULL }, // CLEAR
|
| - { NULL, src_modeproc16_255, NULL },
|
| - { dst_modeproc16, dst_modeproc16, dst_modeproc16 },
|
| - { srcover_modeproc16_0, srcover_modeproc16_255, NULL },
|
| - { dstover_modeproc16_0, dstover_modeproc16_255, NULL },
|
| - { NULL, srcin_modeproc16_255, NULL },
|
| - { NULL, dstin_modeproc16_255, NULL },
|
| - { NULL, NULL, NULL },// SRC_OUT
|
| - { dstout_modeproc16_0, NULL, NULL },
|
| - { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 },
|
| - { NULL, dstatop_modeproc16_255, NULL },
|
| - { NULL, NULL, NULL }, // XOR
|
| - { darken_modeproc16_0, darken_modeproc16_255, NULL },
|
| - { lighten_modeproc16_0, lighten_modeproc16_255, NULL },
|
| - { NULL, NULL, NULL },//multiply
|
| - { NULL, NULL, NULL }// screen
|
| -};
|
| -
|
| -SkXfermodeProc16 SkPorterDuff::GetXfermodeProc16(Mode mode, SkColor srcColor) {
|
| - SkXfermodeProc16 proc16 = NULL;
|
| -
|
| - if ((unsigned)mode < SkPorterDuff::kModeCount) {
|
| - const Proc16Rec& rec = gPorterDuffModeProcs16[mode];
|
| -
|
| - unsigned a = SkColorGetA(srcColor);
|
| -
|
| - if (0 == a) {
|
| - proc16 = rec.fProc16_0;
|
| - } else if (255 == a) {
|
| - proc16 = rec.fProc16_255;
|
| - } else {
|
| - proc16 = rec.fProc16_General;
|
| - }
|
| - }
|
| - return proc16;
|
| -}
|
| -
|
|
|