diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/include/core/SkXfermode.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/include/core/SkXfermode.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,295 @@ + +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef SkXfermode_DEFINED +#define SkXfermode_DEFINED + +#include "SkFlattenable.h" +#include "SkColor.h" + +class GrEffectRef; +class GrTexture; +class SkString; + +/** \class SkXfermode + * + * SkXfermode is the base class for objects that are called to implement custom + * "transfer-modes" in the drawing pipeline. The static function Create(Modes) + * can be called to return an instance of any of the predefined subclasses as + * specified in the Modes enum. When an SkXfermode is assigned to an SkPaint, + * then objects drawn with that paint have the xfermode applied. + * + * All subclasses are required to be reentrant-safe : it must be legal to share + * the same instance between several threads. + */ +class SK_API SkXfermode : public SkFlattenable { +public: + SK_DECLARE_INST_COUNT(SkXfermode) + + virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const; + virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const; + virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const; + + /** Enum of possible coefficients to describe some xfermodes + */ + enum Coeff { + kZero_Coeff, /** 0 */ + kOne_Coeff, /** 1 */ + kSC_Coeff, /** src color */ + kISC_Coeff, /** inverse src color (i.e. 1 - sc) */ + kDC_Coeff, /** dst color */ + kIDC_Coeff, /** inverse dst color (i.e. 1 - dc) */ + kSA_Coeff, /** src alpha */ + kISA_Coeff, /** inverse src alpha (i.e. 1 - sa) */ + kDA_Coeff, /** dst alpha */ + kIDA_Coeff, /** inverse dst alpha (i.e. 1 - da) */ + + kCoeffCount + }; + + /** If the xfermode can be expressed as an equation using the coefficients + in Coeff, then asCoeff() returns true, and sets (if not null) src and + dst accordingly. + + result = src_coeff * src_color + dst_coeff * dst_color; + + As examples, here are some of the porterduff coefficients + + MODE SRC_COEFF DST_COEFF + clear zero zero + src one zero + dst zero one + srcover one isa + dstover ida one + */ + virtual bool asCoeff(Coeff* src, Coeff* dst) const; + + /** + * The same as calling xfermode->asCoeff(..), except that this also checks + * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode. + */ + static bool AsCoeff(const SkXfermode*, Coeff* src, Coeff* dst); + + /** List of predefined xfermodes. + The algebra for the modes uses the following symbols: + Sa, Sc - source alpha and color + Da, Dc - destination alpha and color (before compositing) + [a, c] - Resulting (alpha, color) values + For these equations, the colors are in premultiplied state. + If no xfermode is specified, kSrcOver is assumed. + The modes are ordered by those that can be expressed as a pair of Coeffs, followed by those + that aren't Coeffs but have separable r,g,b computations, and finally + those that are not separable. + */ + enum Mode { + kClear_Mode, //!< [0, 0] + kSrc_Mode, //!< [Sa, Sc] + kDst_Mode, //!< [Da, Dc] + kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc] + kDstOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc] + kSrcIn_Mode, //!< [Sa * Da, Sc * Da] + kDstIn_Mode, //!< [Sa * Da, Sa * Dc] + kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)] + kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] + kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] + kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] + kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] + kPlus_Mode, //!< [Sa + Da, Sc + Dc] + kModulate_Mode, // multiplies all components (= alpha and color) + + // Following blend modes are defined in the CSS Compositing standard: + // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending + kScreen_Mode, + kLastCoeffMode = kScreen_Mode, + + kOverlay_Mode, + kDarken_Mode, + kLighten_Mode, + kColorDodge_Mode, + kColorBurn_Mode, + kHardLight_Mode, + kSoftLight_Mode, + kDifference_Mode, + kExclusion_Mode, + kMultiply_Mode, + kLastSeparableMode = kMultiply_Mode, + + kHue_Mode, + kSaturation_Mode, + kColor_Mode, + kLuminosity_Mode, + kLastMode = kLuminosity_Mode + }; + + /** + * Gets the name of the Mode as a string. + */ + static const char* ModeName(Mode); + + /** + * If the xfermode is one of the modes in the Mode enum, then asMode() + * returns true and sets (if not null) mode accordingly. Otherwise it + * returns false and ignores the mode parameter. + */ + virtual bool asMode(Mode* mode) const; + + /** + * The same as calling xfermode->asMode(mode), except that this also checks + * if the xfermode is NULL, and if so, treats it as kSrcOver_Mode. + */ + static bool AsMode(const SkXfermode*, Mode* mode); + + /** + * Returns true if the xfermode claims to be the specified Mode. This works + * correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus + * you can say this without checking for a null... + * + * If (SkXfermode::IsMode(paint.getXfermode(), + * SkXfermode::kDstOver_Mode)) { + * ... + * } + */ + static bool IsMode(const SkXfermode* xfer, Mode mode); + + /** Return an SkXfermode object for the specified mode. + */ + static SkXfermode* Create(Mode mode); + + /** Return a function pointer to a routine that applies the specified + porter-duff transfer mode. + */ + static SkXfermodeProc GetProc(Mode mode); + + /** Return a function pointer to a routine that applies the specified + porter-duff transfer mode and srcColor to a 16bit device color. Note, + if the mode+srcColor might return a non-opaque color, then there is not + 16bit proc, and this will return NULL. + */ + static SkXfermodeProc16 GetProc16(Mode mode, SkColor srcColor); + + /** + * If the specified mode can be represented by a pair of Coeff, then return + * true and set (if not NULL) the corresponding coeffs. If the mode is + * not representable as a pair of Coeffs, return false and ignore the + * src and dst parameters. + */ + static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst); + + SK_ATTR_DEPRECATED("use AsMode(...)") + static bool IsMode(const SkXfermode* xfer, Mode* mode) { + return AsMode(xfer, mode); + } + + /** A subclass may implement this factory function to work with the GPU backend. It is legal + to call this with all params NULL to simply test the return value. If effect is non-NULL + then the xfermode may optionally allocate an effect to return and the caller as *effect. + The caller will install it and own a ref to it. Since the xfermode may or may not assign + *effect, the caller should set *effect to NULL beforehand. background specifies the + texture to use as the background for compositing, and should be accessed in the effect's + fragment shader. If NULL, the effect should request access to destination color + (setWillReadDstColor()), and use that in the fragment shader (builder->dstColor()). + */ + virtual bool asNewEffect(GrEffectRef** effect, GrTexture* background = NULL) const; + + /** Returns true if the xfermode can be expressed as coeffs (src, dst), or as an effect + (effect). This helper calls the asCoeff() and asNewEffect() virtuals. If the xfermode is + NULL, it is treated as kSrcOver_Mode. It is legal to call this with all params NULL to + simply test the return value. effect, src, and dst must all be NULL or all non-NULL. + */ + static bool AsNewEffectOrCoeff(SkXfermode*, + GrEffectRef** effect, + Coeff* src, + Coeff* dst, + GrTexture* background = NULL); + + SK_TO_STRING_PUREVIRT() + SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() + SK_DEFINE_FLATTENABLE_TYPE(SkXfermode) + +protected: + SkXfermode(SkReadBuffer& rb) : SkFlattenable(rb) {} + + /** The default implementation of xfer32/xfer16/xferA8 in turn call this + method, 1 color at a time (upscaled to a SkPMColor). The default + implmentation of this method just returns dst. If performance is + important, your subclass should override xfer32/xfer16/xferA8 directly. + + This method will not be called directly by the client, so it need not + be implemented if your subclass has overridden xfer32/xfer16/xferA8 + */ + virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const; + +#ifdef SK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS +public: +#endif + SkXfermode() {} + +private: + enum { + kModeCount = kLastMode + 1 + }; + + friend class SkGraphics; + static void Term(); + + typedef SkFlattenable INHERITED; +}; + +/////////////////////////////////////////////////////////////////////////////// + +/** \class SkProcXfermode + + SkProcXfermode is a xfermode that applies the specified proc to its colors. + This class is not exported to java. +*/ +class SkProcXfermode : public SkXfermode { +public: + static SkProcXfermode* Create(SkXfermodeProc proc) { + return SkNEW_ARGS(SkProcXfermode, (proc)); + } + + // overrides from SkXfermode + virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const SK_OVERRIDE; + virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const SK_OVERRIDE; + virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count, + const SkAlpha aa[]) const SK_OVERRIDE; + + SK_TO_STRING_OVERRIDE() + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcXfermode) + +protected: + SkProcXfermode(SkReadBuffer&); + virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE; + + // allow subclasses to update this after we unflatten + void setProc(SkXfermodeProc proc) { + fProc = proc; + } + + SkXfermodeProc getProc() const { + return fProc; + } + +#ifdef SK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS +public: +#endif + SkProcXfermode(SkXfermodeProc proc) : fProc(proc) {} + +private: + SkXfermodeProc fProc; + + typedef SkXfermode INHERITED; +}; + +#endif