Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef SkXfermode_DEFINED
     11 #define SkXfermode_DEFINED
     12 
     13 #include "SkFlattenable.h"
     14 #include "SkColor.h"
     15 
     16 class GrEffectRef;
     17 class GrTexture;
     18 class SkString;
     19 
     20 /** \class SkXfermode
     21  *
     22  *  SkXfermode is the base class for objects that are called to implement custom
     23  *  "transfer-modes" in the drawing pipeline. The static function Create(Modes)
     24  *  can be called to return an instance of any of the predefined subclasses as
     25  *  specified in the Modes enum. When an SkXfermode is assigned to an SkPaint,
     26  *  then objects drawn with that paint have the xfermode applied.
     27  *
     28  *  All subclasses are required to be reentrant-safe : it must be legal to share
     29  *  the same instance between several threads.
     30  */
     31 class SK_API SkXfermode : public SkFlattenable {
     32 public:
     33     SK_DECLARE_INST_COUNT(SkXfermode)
     34 
     35     SkXfermode() {}
     36 
     37     virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
     38                         const SkAlpha aa[]) const;
     39     virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
     40                         const SkAlpha aa[]) const;
     41     virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
     42                         const SkAlpha aa[]) const;
     43 
     44     /** Enum of possible coefficients to describe some xfermodes
     45      */
     46     enum Coeff {
     47         kZero_Coeff,    /** 0 */
     48         kOne_Coeff,     /** 1 */
     49         kSC_Coeff,      /** src color */
     50         kISC_Coeff,     /** inverse src color (i.e. 1 - sc) */
     51         kDC_Coeff,      /** dst color */
     52         kIDC_Coeff,     /** inverse dst color (i.e. 1 - dc) */
     53         kSA_Coeff,      /** src alpha */
     54         kISA_Coeff,     /** inverse src alpha (i.e. 1 - sa) */
     55         kDA_Coeff,      /** dst alpha */
     56         kIDA_Coeff,     /** inverse dst alpha (i.e. 1 - da) */
     57 
     58         kCoeffCount
     59     };
     60 
     61     /** If the xfermode can be expressed as an equation using the coefficients
     62         in Coeff, then asCoeff() returns true, and sets (if not null) src and
     63         dst accordingly.
     64 
     65             result = src_coeff * src_color + dst_coeff * dst_color;
     66 
     67         As examples, here are some of the porterduff coefficients
     68 
     69         MODE        SRC_COEFF       DST_COEFF
     70         clear       zero            zero
     71         src         one             zero
     72         dst         zero            one
     73         srcover     one             isa
     74         dstover     ida             one
     75      */
     76     virtual bool asCoeff(Coeff* src, Coeff* dst) const;
     77 
     78     /**
     79      *  The same as calling xfermode->asCoeff(..), except that this also checks
     80      *  if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
     81      */
     82     static bool AsCoeff(const SkXfermode*, Coeff* src, Coeff* dst);
     83 
     84     /** List of predefined xfermodes.
     85         The algebra for the modes uses the following symbols:
     86         Sa, Sc  - source alpha and color
     87         Da, Dc - destination alpha and color (before compositing)
     88         [a, c] - Resulting (alpha, color) values
     89         For these equations, the colors are in premultiplied state.
     90         If no xfermode is specified, kSrcOver is assumed.
     91         The modes are ordered by those that can be expressed as a pair of Coeffs, followed by those
     92         that aren't Coeffs but have separable r,g,b computations, and finally
     93         those that are not separable.
     94      */
     95     enum Mode {
     96         kClear_Mode,    //!< [0, 0]
     97         kSrc_Mode,      //!< [Sa, Sc]
     98         kDst_Mode,      //!< [Da, Dc]
     99         kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc]
    100         kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc]
    101         kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
    102         kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
    103         kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
    104         kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
    105         kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
    106         kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
    107         kXor_Mode,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
    108         kPlus_Mode,     //!< [Sa + Da, Sc + Dc]
    109         kModulate_Mode, // multiplies all components (= alpha and color)
    110 
    111         // Following blend modes are defined in the CSS Compositing standard:
    112         // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending
    113         kScreen_Mode,
    114         kLastCoeffMode = kScreen_Mode,
    115 
    116         kOverlay_Mode,
    117         kDarken_Mode,
    118         kLighten_Mode,
    119         kColorDodge_Mode,
    120         kColorBurn_Mode,
    121         kHardLight_Mode,
    122         kSoftLight_Mode,
    123         kDifference_Mode,
    124         kExclusion_Mode,
    125         kMultiply_Mode,
    126         kLastSeparableMode = kMultiply_Mode,
    127 
    128         kHue_Mode,
    129         kSaturation_Mode,
    130         kColor_Mode,
    131         kLuminosity_Mode,
    132         kLastMode = kLuminosity_Mode
    133     };
    134 
    135     /**
    136      * Gets the name of the Mode as a string.
    137      */
    138     static const char* ModeName(Mode);
    139 
    140     /**
    141      *  If the xfermode is one of the modes in the Mode enum, then asMode()
    142      *  returns true and sets (if not null) mode accordingly. Otherwise it
    143      *  returns false and ignores the mode parameter.
    144      */
    145     virtual bool asMode(Mode* mode) const;
    146 
    147     /**
    148      *  The same as calling xfermode->asMode(mode), except that this also checks
    149      *  if the xfermode is NULL, and if so, treats it as kSrcOver_Mode.
    150      */
    151     static bool AsMode(const SkXfermode*, Mode* mode);
    152 
    153     /**
    154      *  Returns true if the xfermode claims to be the specified Mode. This works
    155      *  correctly even if the xfermode is NULL (which equates to kSrcOver.) Thus
    156      *  you can say this without checking for a null...
    157      *
    158      *  If (SkXfermode::IsMode(paint.getXfermode(),
    159      *                         SkXfermode::kDstOver_Mode)) {
    160      *      ...
    161      *  }
    162      */
    163     static bool IsMode(const SkXfermode* xfer, Mode mode);
    164 
    165     /** Return an SkXfermode object for the specified mode.
    166      */
    167     static SkXfermode* Create(Mode mode);
    168 
    169     /** Return a function pointer to a routine that applies the specified
    170         porter-duff transfer mode.
    171      */
    172     static SkXfermodeProc GetProc(Mode mode);
    173 
    174     /** Return a function pointer to a routine that applies the specified
    175         porter-duff transfer mode and srcColor to a 16bit device color. Note,
    176         if the mode+srcColor might return a non-opaque color, then there is not
    177         16bit proc, and this will return NULL.
    178       */
    179     static SkXfermodeProc16 GetProc16(Mode mode, SkColor srcColor);
    180 
    181     /**
    182      *  If the specified mode can be represented by a pair of Coeff, then return
    183      *  true and set (if not NULL) the corresponding coeffs. If the mode is
    184      *  not representable as a pair of Coeffs, return false and ignore the
    185      *  src and dst parameters.
    186      */
    187     static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
    188 
    189     SK_ATTR_DEPRECATED("use AsMode(...)")
    190     static bool IsMode(const SkXfermode* xfer, Mode* mode) {
    191         return AsMode(xfer, mode);
    192     }
    193 
    194     /** A subclass may implement this factory function to work with the GPU backend. It is legal
    195         to call this with all params NULL to simply test the return value. If effect is non-NULL
    196         then the xfermode may optionally allocate an effect to return and the caller as *effect.
    197         The caller will install it and own a ref to it. Since the xfermode may or may not assign
    198         *effect, the caller should set *effect to NULL beforehand. background specifies the
    199         texture to use as the background for compositing, and should be accessed in the effect's
    200         fragment shader. If NULL, the effect should request access to destination color
    201         (setWillReadDstColor()), and use that in the fragment shader (builder->dstColor()).
    202      */
    203     virtual bool asNewEffect(GrEffectRef** effect, GrTexture* background = NULL) const;
    204 
    205     /** Returns true if the xfermode can be expressed as coeffs (src, dst), or as an effect
    206         (effect). This helper calls the asCoeff() and asNewEffect() virtuals. If the xfermode is
    207         NULL, it is treated as kSrcOver_Mode. It is legal to call this with all params NULL to
    208         simply test the return value.  effect, src, and dst must all be NULL or all non-NULL.
    209      */
    210     static bool AsNewEffectOrCoeff(SkXfermode*,
    211                                    GrEffectRef** effect,
    212                                    Coeff* src,
    213                                    Coeff* dst,
    214                                    GrTexture* background = NULL);
    215 
    216     SkDEVCODE(virtual void toString(SkString* str) const = 0;)
    217     SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
    218     SK_DEFINE_FLATTENABLE_TYPE(SkXfermode)
    219 
    220 protected:
    221     SkXfermode(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {}
    222 
    223     /** The default implementation of xfer32/xfer16/xferA8 in turn call this
    224         method, 1 color at a time (upscaled to a SkPMColor). The default
    225         implmentation of this method just returns dst. If performance is
    226         important, your subclass should override xfer32/xfer16/xferA8 directly.
    227 
    228         This method will not be called directly by the client, so it need not
    229         be implemented if your subclass has overridden xfer32/xfer16/xferA8
    230     */
    231     virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const;
    232 
    233 private:
    234     enum {
    235         kModeCount = kLastMode + 1
    236     };
    237 
    238     friend class SkGraphics;
    239     static void Term();
    240 
    241     typedef SkFlattenable INHERITED;
    242 };
    243 
    244 ///////////////////////////////////////////////////////////////////////////////
    245 
    246 /** \class SkProcXfermode
    247 
    248     SkProcXfermode is a xfermode that applies the specified proc to its colors.
    249     This class is not exported to java.
    250 */
    251 class SkProcXfermode : public SkXfermode {
    252 public:
    253     SkProcXfermode(SkXfermodeProc proc) : fProc(proc) {}
    254 
    255     // overrides from SkXfermode
    256     virtual void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
    257                         const SkAlpha aa[]) const SK_OVERRIDE;
    258     virtual void xfer16(uint16_t dst[], const SkPMColor src[], int count,
    259                         const SkAlpha aa[]) const SK_OVERRIDE;
    260     virtual void xferA8(SkAlpha dst[], const SkPMColor src[], int count,
    261                         const SkAlpha aa[]) const SK_OVERRIDE;
    262 
    263     SK_DEVELOPER_TO_STRING()
    264     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcXfermode)
    265 
    266 protected:
    267     SkProcXfermode(SkFlattenableReadBuffer&);
    268     virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
    269 
    270     // allow subclasses to update this after we unflatten
    271     void setProc(SkXfermodeProc proc) {
    272         fProc = proc;
    273     }
    274 
    275     SkXfermodeProc getProc() const {
    276         return fProc;
    277     }
    278 
    279 private:
    280     SkXfermodeProc  fProc;
    281 
    282     typedef SkXfermode INHERITED;
    283 };
    284 
    285 #endif
    286